• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2014 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  siaddrlib.cpp
30 * @brief Contains the implementation for the SiLib class.
31 ****************************************************************************************************
32 */
33 
34 #include "siaddrlib.h"
35 #include "si_gb_reg.h"
36 
37 #include "amdgpu_asic_addr.h"
38 
39 ////////////////////////////////////////////////////////////////////////////////////////////////////
40 ////////////////////////////////////////////////////////////////////////////////////////////////////
41 namespace Addr
42 {
43 
44 /**
45 ****************************************************************************************************
46 *   SiHwlInit
47 *
48 *   @brief
49 *       Creates an SiLib object.
50 *
51 *   @return
52 *       Returns an SiLib object pointer.
53 ****************************************************************************************************
54 */
SiHwlInit(const Client * pClient)55 Lib* SiHwlInit(const Client* pClient)
56 {
57     return V1::SiLib::CreateObj(pClient);
58 }
59 
60 namespace V1
61 {
62 
63 // We don't support MSAA for equation
64 const BOOL_32 SiLib::m_EquationSupport[SiLib::TileTableSize][SiLib::MaxNumElementBytes] =
65 {
66     {TRUE,  TRUE,  TRUE,  FALSE, FALSE},    //  0, non-AA compressed depth or any stencil
67     {FALSE, FALSE, FALSE, FALSE, FALSE},    //  1, 2xAA/4xAA compressed depth with or without stencil
68     {FALSE, FALSE, FALSE, FALSE, FALSE},    //  2, 8xAA compressed depth with or without stencil
69     {FALSE, TRUE,  FALSE, FALSE, FALSE},    //  3, 16 bpp depth PRT (non-MSAA), don't support uncompressed depth
70     {TRUE,  TRUE,  TRUE,  FALSE, FALSE},    //  4, 1D depth
71     {FALSE, FALSE, FALSE, FALSE, FALSE},    //  5, 16 bpp depth PRT (4xMSAA)
72     {FALSE, FALSE, TRUE,  FALSE, FALSE},    //  6, 32 bpp depth PRT (non-MSAA)
73     {FALSE, FALSE, FALSE, FALSE, FALSE},    //  7, 32 bpp depth PRT (4xMSAA)
74     {TRUE,  TRUE,  TRUE,  TRUE,  TRUE },    //  8, Linear
75     {TRUE,  TRUE,  TRUE,  TRUE,  TRUE },    //  9, 1D display
76     {TRUE,  FALSE, FALSE, FALSE, FALSE},    // 10, 8 bpp color (displayable)
77     {FALSE, TRUE,  FALSE, FALSE, FALSE},    // 11, 16 bpp color (displayable)
78     {FALSE, FALSE, TRUE,  TRUE,  FALSE},    // 12, 32/64 bpp color (displayable)
79     {TRUE,  TRUE,  TRUE,  TRUE,  TRUE },    // 13, 1D thin
80     {TRUE,  FALSE, FALSE, FALSE, FALSE},    // 14, 8 bpp color non-displayable
81     {FALSE, TRUE,  FALSE, FALSE, FALSE},    // 15, 16 bpp color non-displayable
82     {FALSE, FALSE, TRUE,  FALSE, FALSE},    // 16, 32 bpp color non-displayable
83     {FALSE, FALSE, FALSE, TRUE,  TRUE },    // 17, 64/128 bpp color non-displayable
84     {TRUE,  TRUE,  TRUE,  TRUE,  TRUE },    // 18, 1D THICK
85     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 19, 2D XTHICK
86     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 20, 2D THICK
87     {TRUE,  FALSE, FALSE, FALSE, FALSE},    // 21, 8 bpp 2D PRTs (non-MSAA)
88     {FALSE, TRUE,  FALSE, FALSE, FALSE},    // 22, 16 bpp 2D PRTs (non-MSAA)
89     {FALSE, FALSE, TRUE,  FALSE, FALSE},    // 23, 32 bpp 2D PRTs (non-MSAA)
90     {FALSE, FALSE, FALSE, TRUE,  FALSE},    // 24, 64 bpp 2D PRTs (non-MSAA)
91     {FALSE, FALSE, FALSE, FALSE, TRUE },    // 25, 128bpp 2D PRTs (non-MSAA)
92     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 26, none
93     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 27, none
94     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 28, none
95     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 29, none
96     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 30, 64bpp 2D PRTs (4xMSAA)
97     {FALSE, FALSE, FALSE, FALSE, FALSE},    // 31, none
98 };
99 
100 /**
101 ****************************************************************************************************
102 *   SiLib::SiLib
103 *
104 *   @brief
105 *       Constructor
106 *
107 ****************************************************************************************************
108 */
SiLib(const Client * pClient)109 SiLib::SiLib(const Client* pClient)
110     :
111     EgBasedLib(pClient),
112     m_noOfEntries(0),
113     m_numEquations(0)
114 {
115     m_class = SI_ADDRLIB;
116     memset(&m_settings, 0, sizeof(m_settings));
117 }
118 
119 /**
120 ****************************************************************************************************
121 *   SiLib::~SiLib
122 *
123 *   @brief
124 *       Destructor
125 ****************************************************************************************************
126 */
~SiLib()127 SiLib::~SiLib()
128 {
129 }
130 
131 /**
132 ****************************************************************************************************
133 *   SiLib::HwlGetPipes
134 *
135 *   @brief
136 *       Get number pipes
137 *   @return
138 *       num pipes
139 ****************************************************************************************************
140 */
HwlGetPipes(const ADDR_TILEINFO * pTileInfo) const141 UINT_32 SiLib::HwlGetPipes(
142     const ADDR_TILEINFO* pTileInfo    ///< [in] Tile info
143     ) const
144 {
145     UINT_32 numPipes;
146 
147     if (pTileInfo)
148     {
149         numPipes = GetPipePerSurf(pTileInfo->pipeConfig);
150     }
151     else
152     {
153         ADDR_ASSERT_ALWAYS();
154         numPipes = m_pipes; // Suppose we should still have a global pipes
155     }
156 
157     return numPipes;
158 }
159 
160 /**
161 ****************************************************************************************************
162 *   SiLib::GetPipePerSurf
163 *   @brief
164 *       get pipe num base on inputing tileinfo->pipeconfig
165 *   @return
166 *       pipe number
167 ****************************************************************************************************
168 */
GetPipePerSurf(AddrPipeCfg pipeConfig) const169 UINT_32 SiLib::GetPipePerSurf(
170     AddrPipeCfg pipeConfig   ///< [in] pipe config
171     ) const
172 {
173     UINT_32 numPipes = 0;
174 
175     switch (pipeConfig)
176     {
177         case ADDR_PIPECFG_P2:
178             numPipes = 2;
179             break;
180         case ADDR_PIPECFG_P4_8x16:
181         case ADDR_PIPECFG_P4_16x16:
182         case ADDR_PIPECFG_P4_16x32:
183         case ADDR_PIPECFG_P4_32x32:
184             numPipes = 4;
185             break;
186         case ADDR_PIPECFG_P8_16x16_8x16:
187         case ADDR_PIPECFG_P8_16x32_8x16:
188         case ADDR_PIPECFG_P8_32x32_8x16:
189         case ADDR_PIPECFG_P8_16x32_16x16:
190         case ADDR_PIPECFG_P8_32x32_16x16:
191         case ADDR_PIPECFG_P8_32x32_16x32:
192         case ADDR_PIPECFG_P8_32x64_32x32:
193             numPipes = 8;
194             break;
195         case ADDR_PIPECFG_P16_32x32_8x16:
196         case ADDR_PIPECFG_P16_32x32_16x16:
197             numPipes = 16;
198             break;
199         default:
200             ADDR_ASSERT(!"Invalid pipe config");
201             numPipes = m_pipes;
202     }
203     return numPipes;
204 }
205 
206 /**
207 ****************************************************************************************************
208 *   SiLib::ComputeBankEquation
209 *
210 *   @brief
211 *       Compute bank equation
212 *
213 *   @return
214 *       If equation can be computed
215 ****************************************************************************************************
216 */
ComputeBankEquation(UINT_32 log2BytesPP,UINT_32 threshX,UINT_32 threshY,ADDR_TILEINFO * pTileInfo,ADDR_EQUATION * pEquation) const217 ADDR_E_RETURNCODE SiLib::ComputeBankEquation(
218     UINT_32         log2BytesPP,    ///< [in] log2 of bytes per pixel
219     UINT_32         threshX,        ///< [in] threshold for x channel
220     UINT_32         threshY,        ///< [in] threshold for y channel
221     ADDR_TILEINFO*  pTileInfo,      ///< [in] tile info
222     ADDR_EQUATION*  pEquation       ///< [out] bank equation
223     ) const
224 {
225     ADDR_E_RETURNCODE retCode = ADDR_OK;
226 
227     UINT_32 pipes = HwlGetPipes(pTileInfo);
228     UINT_32 bankXStart = 3 + Log2(pipes) + Log2(pTileInfo->bankWidth);
229     UINT_32 bankYStart = 3 + Log2(pTileInfo->bankHeight);
230 
231     ADDR_CHANNEL_SETTING x3 = InitChannel(1, 0, log2BytesPP + bankXStart);
232     ADDR_CHANNEL_SETTING x4 = InitChannel(1, 0, log2BytesPP + bankXStart + 1);
233     ADDR_CHANNEL_SETTING x5 = InitChannel(1, 0, log2BytesPP + bankXStart + 2);
234     ADDR_CHANNEL_SETTING x6 = InitChannel(1, 0, log2BytesPP + bankXStart + 3);
235     ADDR_CHANNEL_SETTING y3 = InitChannel(1, 1, bankYStart);
236     ADDR_CHANNEL_SETTING y4 = InitChannel(1, 1, bankYStart + 1);
237     ADDR_CHANNEL_SETTING y5 = InitChannel(1, 1, bankYStart + 2);
238     ADDR_CHANNEL_SETTING y6 = InitChannel(1, 1, bankYStart + 3);
239 
240     x3.value = (threshX > bankXStart)     ? x3.value : 0;
241     x4.value = (threshX > bankXStart + 1) ? x4.value : 0;
242     x5.value = (threshX > bankXStart + 2) ? x5.value : 0;
243     x6.value = (threshX > bankXStart + 3) ? x6.value : 0;
244     y3.value = (threshY > bankYStart)     ? y3.value : 0;
245     y4.value = (threshY > bankYStart + 1) ? y4.value : 0;
246     y5.value = (threshY > bankYStart + 2) ? y5.value : 0;
247     y6.value = (threshY > bankYStart + 3) ? y6.value : 0;
248 
249     switch (pTileInfo->banks)
250     {
251         case 16:
252             if (pTileInfo->macroAspectRatio == 1)
253             {
254                 pEquation->addr[0] = y6;
255                 pEquation->xor1[0] = x3;
256                 pEquation->addr[1] = y5;
257                 pEquation->xor1[1] = y6;
258                 pEquation->xor2[1] = x4;
259                 pEquation->addr[2] = y4;
260                 pEquation->xor1[2] = x5;
261                 pEquation->addr[3] = y3;
262                 pEquation->xor1[3] = x6;
263             }
264             else if (pTileInfo->macroAspectRatio == 2)
265             {
266                 pEquation->addr[0] = x3;
267                 pEquation->xor1[0] = y6;
268                 pEquation->addr[1] = y5;
269                 pEquation->xor1[1] = y6;
270                 pEquation->xor2[1] = x4;
271                 pEquation->addr[2] = y4;
272                 pEquation->xor1[2] = x5;
273                 pEquation->addr[3] = y3;
274                 pEquation->xor1[3] = x6;
275             }
276             else if (pTileInfo->macroAspectRatio == 4)
277             {
278                 pEquation->addr[0] = x3;
279                 pEquation->xor1[0] = y6;
280                 pEquation->addr[1] = x4;
281                 pEquation->xor1[1] = y5;
282                 pEquation->xor2[1] = y6;
283                 pEquation->addr[2] = y4;
284                 pEquation->xor1[2] = x5;
285                 pEquation->addr[3] = y3;
286                 pEquation->xor1[3] = x6;
287             }
288             else if (pTileInfo->macroAspectRatio == 8)
289             {
290                 pEquation->addr[0] = x3;
291                 pEquation->xor1[0] = y6;
292                 pEquation->addr[1] = x4;
293                 pEquation->xor1[1] = y5;
294                 pEquation->xor2[1] = y6;
295                 pEquation->addr[2] = x5;
296                 pEquation->xor1[2] = y4;
297                 pEquation->addr[3] = y3;
298                 pEquation->xor1[3] = x6;
299             }
300             else
301             {
302                 ADDR_ASSERT_ALWAYS();
303             }
304             pEquation->numBits = 4;
305             break;
306         case 8:
307             if (pTileInfo->macroAspectRatio == 1)
308             {
309                 pEquation->addr[0] = y5;
310                 pEquation->xor1[0] = x3;
311                 pEquation->addr[1] = y4;
312                 pEquation->xor1[1] = y5;
313                 pEquation->xor2[1] = x4;
314                 pEquation->addr[2] = y3;
315                 pEquation->xor1[2] = x5;
316             }
317             else if (pTileInfo->macroAspectRatio == 2)
318             {
319                 pEquation->addr[0] = x3;
320                 pEquation->xor1[0] = y5;
321                 pEquation->addr[1] = y4;
322                 pEquation->xor1[1] = y5;
323                 pEquation->xor2[1] = x4;
324                 pEquation->addr[2] = y3;
325                 pEquation->xor1[2] = x5;
326             }
327             else if (pTileInfo->macroAspectRatio == 4)
328             {
329                 pEquation->addr[0] = x3;
330                 pEquation->xor1[0] = y5;
331                 pEquation->addr[1] = x4;
332                 pEquation->xor1[1] = y4;
333                 pEquation->xor2[1] = y5;
334                 pEquation->addr[2] = y3;
335                 pEquation->xor1[2] = x5;
336             }
337             else
338             {
339                 ADDR_ASSERT_ALWAYS();
340             }
341             pEquation->numBits = 3;
342             break;
343         case 4:
344             if (pTileInfo->macroAspectRatio == 1)
345             {
346                 pEquation->addr[0] = y4;
347                 pEquation->xor1[0] = x3;
348                 pEquation->addr[1] = y3;
349                 pEquation->xor1[1] = x4;
350             }
351             else if (pTileInfo->macroAspectRatio == 2)
352             {
353                 pEquation->addr[0] = x3;
354                 pEquation->xor1[0] = y4;
355                 pEquation->addr[1] = y3;
356                 pEquation->xor1[1] = x4;
357             }
358             else
359             {
360                 pEquation->addr[0] = x3;
361                 pEquation->xor1[0] = y4;
362                 pEquation->addr[1] = x4;
363                 pEquation->xor1[1] = y3;
364             }
365             pEquation->numBits = 2;
366             break;
367         case 2:
368             if (pTileInfo->macroAspectRatio == 1)
369             {
370                 pEquation->addr[0] = y3;
371                 pEquation->xor1[0] = x3;
372             }
373             else
374             {
375                 pEquation->addr[0] = x3;
376                 pEquation->xor1[0] = y3;
377             }
378             pEquation->numBits = 1;
379             break;
380         default:
381             pEquation->numBits = 0;
382             retCode = ADDR_NOTSUPPORTED;
383             ADDR_ASSERT_ALWAYS();
384             break;
385     }
386 
387     for (UINT_32 i = 0; i < pEquation->numBits; i++)
388     {
389         if (pEquation->addr[i].value == 0)
390         {
391             if (pEquation->xor1[i].value == 0)
392             {
393                 // 00X -> X00
394                 pEquation->addr[i].value = pEquation->xor2[i].value;
395                 pEquation->xor2[i].value = 0;
396             }
397             else
398             {
399                 pEquation->addr[i].value = pEquation->xor1[i].value;
400 
401                 if (pEquation->xor2[i].value != 0)
402                 {
403                     // 0XY -> XY0
404                     pEquation->xor1[i].value = pEquation->xor2[i].value;
405                     pEquation->xor2[i].value = 0;
406                 }
407                 else
408                 {
409                     // 0X0 -> X00
410                     pEquation->xor1[i].value = 0;
411                 }
412             }
413         }
414         else if (pEquation->xor1[i].value == 0)
415         {
416             if (pEquation->xor2[i].value != 0)
417             {
418                 // X0Y -> XY0
419                 pEquation->xor1[i].value = pEquation->xor2[i].value;
420                 pEquation->xor2[i].value = 0;
421             }
422         }
423     }
424 
425     if ((pTileInfo->bankWidth == 1) &&
426         ((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) ||
427          (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)))
428     {
429         retCode = ADDR_NOTSUPPORTED;
430     }
431 
432     return retCode;
433 }
434 
435 /**
436 ****************************************************************************************************
437 *   SiLib::ComputePipeEquation
438 *
439 *   @brief
440 *       Compute pipe equation
441 *
442 *   @return
443 *       If equation can be computed
444 ****************************************************************************************************
445 */
ComputePipeEquation(UINT_32 log2BytesPP,UINT_32 threshX,UINT_32 threshY,ADDR_TILEINFO * pTileInfo,ADDR_EQUATION * pEquation) const446 ADDR_E_RETURNCODE SiLib::ComputePipeEquation(
447     UINT_32        log2BytesPP, ///< [in] Log2 of bytes per pixel
448     UINT_32        threshX,     ///< [in] Threshold for X channel
449     UINT_32        threshY,     ///< [in] Threshold for Y channel
450     ADDR_TILEINFO* pTileInfo,   ///< [in] Tile info
451     ADDR_EQUATION* pEquation    ///< [out] Pipe configure
452     ) const
453 {
454     ADDR_E_RETURNCODE retCode = ADDR_OK;
455 
456     ADDR_CHANNEL_SETTING* pAddr = pEquation->addr;
457     ADDR_CHANNEL_SETTING* pXor1 = pEquation->xor1;
458     ADDR_CHANNEL_SETTING* pXor2 = pEquation->xor2;
459 
460     ADDR_CHANNEL_SETTING x3 = InitChannel(1, 0, 3 + log2BytesPP);
461     ADDR_CHANNEL_SETTING x4 = InitChannel(1, 0, 4 + log2BytesPP);
462     ADDR_CHANNEL_SETTING x5 = InitChannel(1, 0, 5 + log2BytesPP);
463     ADDR_CHANNEL_SETTING x6 = InitChannel(1, 0, 6 + log2BytesPP);
464     ADDR_CHANNEL_SETTING y3 = InitChannel(1, 1, 3);
465     ADDR_CHANNEL_SETTING y4 = InitChannel(1, 1, 4);
466     ADDR_CHANNEL_SETTING y5 = InitChannel(1, 1, 5);
467     ADDR_CHANNEL_SETTING y6 = InitChannel(1, 1, 6);
468 
469     x3.value = (threshX > 3) ? x3.value : 0;
470     x4.value = (threshX > 4) ? x4.value : 0;
471     x5.value = (threshX > 5) ? x5.value : 0;
472     x6.value = (threshX > 6) ? x6.value : 0;
473     y3.value = (threshY > 3) ? y3.value : 0;
474     y4.value = (threshY > 4) ? y4.value : 0;
475     y5.value = (threshY > 5) ? y5.value : 0;
476     y6.value = (threshY > 6) ? y6.value : 0;
477 
478     switch (pTileInfo->pipeConfig)
479     {
480         case ADDR_PIPECFG_P2:
481             pAddr[0] = x3;
482             pXor1[0] = y3;
483             pEquation->numBits = 1;
484             break;
485         case ADDR_PIPECFG_P4_8x16:
486             pAddr[0] = x4;
487             pXor1[0] = y3;
488             pAddr[1] = x3;
489             pXor1[1] = y4;
490             pEquation->numBits = 2;
491             break;
492         case ADDR_PIPECFG_P4_16x16:
493             pAddr[0] = x3;
494             pXor1[0] = y3;
495             pXor2[0] = x4;
496             pAddr[1] = x4;
497             pXor1[1] = y4;
498             pEquation->numBits = 2;
499             break;
500         case ADDR_PIPECFG_P4_16x32:
501             pAddr[0] = x3;
502             pXor1[0] = y3;
503             pXor2[0] = x4;
504             pAddr[1] = x4;
505             pXor1[1] = y5;
506             pEquation->numBits = 2;
507             break;
508         case ADDR_PIPECFG_P4_32x32:
509             pAddr[0] = x3;
510             pXor1[0] = y3;
511             pXor2[0] = x5;
512             pAddr[1] = x5;
513             pXor1[1] = y5;
514             pEquation->numBits = 2;
515             break;
516         case ADDR_PIPECFG_P8_16x16_8x16:
517             pAddr[0] = x4;
518             pXor1[0] = y3;
519             pXor2[0] = x5;
520             pAddr[1] = x3;
521             pXor1[1] = y5;
522             pEquation->numBits = 3;
523             break;
524         case ADDR_PIPECFG_P8_16x32_8x16:
525             pAddr[0] = x4;
526             pXor1[0] = y3;
527             pXor2[0] = x5;
528             pAddr[1] = x3;
529             pXor1[1] = y4;
530             pAddr[2] = x4;
531             pXor1[2] = y5;
532             pEquation->numBits = 3;
533             break;
534         case ADDR_PIPECFG_P8_16x32_16x16:
535             pAddr[0] = x3;
536             pXor1[0] = y3;
537             pXor2[0] = x4;
538             pAddr[1] = x5;
539             pXor1[1] = y4;
540             pAddr[2] = x4;
541             pXor1[2] = y5;
542             pEquation->numBits = 3;
543             break;
544         case ADDR_PIPECFG_P8_32x32_8x16:
545             pAddr[0] = x4;
546             pXor1[0] = y3;
547             pXor2[0] = x5;
548             pAddr[1] = x3;
549             pXor1[1] = y4;
550             pAddr[2] = x5;
551             pXor1[2] = y5;
552             pEquation->numBits = 3;
553             break;
554         case ADDR_PIPECFG_P8_32x32_16x16:
555             pAddr[0] = x3;
556             pXor1[0] = y3;
557             pXor2[0] = x4;
558             pAddr[1] = x4;
559             pXor1[1] = y4;
560             pAddr[2] = x5;
561             pXor1[2] = y5;
562             pEquation->numBits = 3;
563             break;
564         case ADDR_PIPECFG_P8_32x32_16x32:
565             pAddr[0] = x3;
566             pXor1[0] = y3;
567             pXor2[0] = x4;
568             pAddr[1] = x4;
569             pXor1[1] = y6;
570             pAddr[2] = x5;
571             pXor1[2] = y5;
572             pEquation->numBits = 3;
573             break;
574         case ADDR_PIPECFG_P8_32x64_32x32:
575             pAddr[0] = x3;
576             pXor1[0] = y3;
577             pXor2[0] = x5;
578             pAddr[1] = x6;
579             pXor1[1] = y5;
580             pAddr[2] = x5;
581             pXor1[2] = y6;
582             pEquation->numBits = 3;
583             break;
584         case ADDR_PIPECFG_P16_32x32_8x16:
585             pAddr[0] = x4;
586             pXor1[0] = y3;
587             pAddr[1] = x3;
588             pXor1[1] = y4;
589             pAddr[2] = x5;
590             pXor1[2] = y6;
591             pAddr[3] = x6;
592             pXor1[3] = y5;
593             pEquation->numBits = 4;
594             break;
595         case ADDR_PIPECFG_P16_32x32_16x16:
596             pAddr[0] = x3;
597             pXor1[0] = y3;
598             pXor2[0] = x4;
599             pAddr[1] = x4;
600             pXor1[1] = y4;
601             pAddr[2] = x5;
602             pXor1[2] = y6;
603             pAddr[3] = x6;
604             pXor1[3] = y5;
605             pEquation->numBits = 4;
606             break;
607         default:
608             ADDR_UNHANDLED_CASE();
609             pEquation->numBits = 0;
610             retCode = ADDR_NOTSUPPORTED;
611             break;
612     }
613 
614     for (UINT_32 i = 0; i < pEquation->numBits; i++)
615     {
616         if (pAddr[i].value == 0)
617         {
618             if (pXor1[i].value == 0)
619             {
620                 pAddr[i].value = pXor2[i].value;
621             }
622             else
623             {
624                 pAddr[i].value = pXor1[i].value;
625                 pXor1[i].value = 0;
626             }
627         }
628     }
629 
630     return retCode;
631 }
632 
633 /**
634 ****************************************************************************************************
635 *   SiLib::ComputePipeFromCoord
636 *
637 *   @brief
638 *       Compute pipe number from coordinates
639 *   @return
640 *       Pipe number
641 ****************************************************************************************************
642 */
ComputePipeFromCoord(UINT_32 x,UINT_32 y,UINT_32 slice,AddrTileMode tileMode,UINT_32 pipeSwizzle,BOOL_32 ignoreSE,ADDR_TILEINFO * pTileInfo) const643 UINT_32 SiLib::ComputePipeFromCoord(
644     UINT_32         x,              ///< [in] x coordinate
645     UINT_32         y,              ///< [in] y coordinate
646     UINT_32         slice,          ///< [in] slice index
647     AddrTileMode    tileMode,       ///< [in] tile mode
648     UINT_32         pipeSwizzle,    ///< [in] pipe swizzle
649     BOOL_32         ignoreSE,       ///< [in] TRUE if shader engines are ignored
650     ADDR_TILEINFO*  pTileInfo       ///< [in] Tile info
651     ) const
652 {
653     UINT_32 pipe;
654     UINT_32 pipeBit0 = 0;
655     UINT_32 pipeBit1 = 0;
656     UINT_32 pipeBit2 = 0;
657     UINT_32 pipeBit3 = 0;
658     UINT_32 sliceRotation;
659     UINT_32 numPipes = 0;
660 
661     UINT_32 tx = x / MicroTileWidth;
662     UINT_32 ty = y / MicroTileHeight;
663     UINT_32 x3 = _BIT(tx,0);
664     UINT_32 x4 = _BIT(tx,1);
665     UINT_32 x5 = _BIT(tx,2);
666     UINT_32 x6 = _BIT(tx,3);
667     UINT_32 y3 = _BIT(ty,0);
668     UINT_32 y4 = _BIT(ty,1);
669     UINT_32 y5 = _BIT(ty,2);
670     UINT_32 y6 = _BIT(ty,3);
671 
672     switch (pTileInfo->pipeConfig)
673     {
674         case ADDR_PIPECFG_P2:
675             pipeBit0 = x3 ^ y3;
676             numPipes = 2;
677             break;
678         case ADDR_PIPECFG_P4_8x16:
679             pipeBit0 = x4 ^ y3;
680             pipeBit1 = x3 ^ y4;
681             numPipes = 4;
682             break;
683         case ADDR_PIPECFG_P4_16x16:
684             pipeBit0 = x3 ^ y3 ^ x4;
685             pipeBit1 = x4 ^ y4;
686             numPipes = 4;
687             break;
688         case ADDR_PIPECFG_P4_16x32:
689             pipeBit0 = x3 ^ y3 ^ x4;
690             pipeBit1 = x4 ^ y5;
691             numPipes = 4;
692             break;
693         case ADDR_PIPECFG_P4_32x32:
694             pipeBit0 = x3 ^ y3 ^ x5;
695             pipeBit1 = x5 ^ y5;
696             numPipes = 4;
697             break;
698         case ADDR_PIPECFG_P8_16x16_8x16:
699             pipeBit0 = x4 ^ y3 ^ x5;
700             pipeBit1 = x3 ^ y5;
701             numPipes = 8;
702             break;
703         case ADDR_PIPECFG_P8_16x32_8x16:
704             pipeBit0 = x4 ^ y3 ^ x5;
705             pipeBit1 = x3 ^ y4;
706             pipeBit2 = x4 ^ y5;
707             numPipes = 8;
708             break;
709         case ADDR_PIPECFG_P8_16x32_16x16:
710             pipeBit0 = x3 ^ y3 ^ x4;
711             pipeBit1 = x5 ^ y4;
712             pipeBit2 = x4 ^ y5;
713             numPipes = 8;
714             break;
715         case ADDR_PIPECFG_P8_32x32_8x16:
716             pipeBit0 = x4 ^ y3 ^ x5;
717             pipeBit1 = x3 ^ y4;
718             pipeBit2 = x5 ^ y5;
719             numPipes = 8;
720             break;
721         case ADDR_PIPECFG_P8_32x32_16x16:
722             pipeBit0 = x3 ^ y3 ^ x4;
723             pipeBit1 = x4 ^ y4;
724             pipeBit2 = x5 ^ y5;
725             numPipes = 8;
726             break;
727         case ADDR_PIPECFG_P8_32x32_16x32:
728             pipeBit0 = x3 ^ y3 ^ x4;
729             pipeBit1 = x4 ^ y6;
730             pipeBit2 = x5 ^ y5;
731             numPipes = 8;
732             break;
733         case ADDR_PIPECFG_P8_32x64_32x32:
734             pipeBit0 = x3 ^ y3 ^ x5;
735             pipeBit1 = x6 ^ y5;
736             pipeBit2 = x5 ^ y6;
737             numPipes = 8;
738             break;
739         case ADDR_PIPECFG_P16_32x32_8x16:
740             pipeBit0 = x4 ^ y3;
741             pipeBit1 = x3 ^ y4;
742             pipeBit2 = x5 ^ y6;
743             pipeBit3 = x6 ^ y5;
744             numPipes = 16;
745             break;
746         case ADDR_PIPECFG_P16_32x32_16x16:
747             pipeBit0 = x3 ^ y3 ^ x4;
748             pipeBit1 = x4 ^ y4;
749             pipeBit2 = x5 ^ y6;
750             pipeBit3 = x6 ^ y5;
751             numPipes = 16;
752             break;
753         default:
754             ADDR_UNHANDLED_CASE();
755             break;
756     }
757     pipe = pipeBit0 | (pipeBit1 << 1) | (pipeBit2 << 2) | (pipeBit3 << 3);
758 
759     UINT_32 microTileThickness = Thickness(tileMode);
760 
761     //
762     // Apply pipe rotation for the slice.
763     //
764     switch (tileMode)
765     {
766         case ADDR_TM_3D_TILED_THIN1:    //fall through thin
767         case ADDR_TM_3D_TILED_THICK:    //fall through thick
768         case ADDR_TM_3D_TILED_XTHICK:
769             sliceRotation =
770                 Max(1, static_cast<INT_32>(numPipes / 2) - 1) * (slice / microTileThickness);
771             break;
772         default:
773             sliceRotation = 0;
774             break;
775     }
776     pipeSwizzle += sliceRotation;
777     pipeSwizzle &= (numPipes - 1);
778 
779     pipe = pipe ^ pipeSwizzle;
780 
781     return pipe;
782 }
783 
784 /**
785 ****************************************************************************************************
786 *   SiLib::ComputeTileCoordFromPipeAndElemIdx
787 *
788 *   @brief
789 *       Compute (x,y) of a tile within a macro tile from address
790 *   @return
791 *       Pipe number
792 ****************************************************************************************************
793 */
ComputeTileCoordFromPipeAndElemIdx(UINT_32 elemIdx,UINT_32 pipe,AddrPipeCfg pipeCfg,UINT_32 pitchInMacroTile,UINT_32 x,UINT_32 y,UINT_32 * pX,UINT_32 * pY) const794 VOID SiLib::ComputeTileCoordFromPipeAndElemIdx(
795     UINT_32         elemIdx,          ///< [in] per pipe element index within a macro tile
796     UINT_32         pipe,             ///< [in] pipe index
797     AddrPipeCfg     pipeCfg,          ///< [in] pipe config
798     UINT_32         pitchInMacroTile, ///< [in] surface pitch in macro tile
799     UINT_32         x,                ///< [in] x coordinate of the (0,0) tile in a macro tile
800     UINT_32         y,                ///< [in] y coordinate of the (0,0) tile in a macro tile
801     UINT_32*        pX,               ///< [out] x coordinate
802     UINT_32*        pY                ///< [out] y coordinate
803     ) const
804 {
805     UINT_32 pipebit0 = _BIT(pipe,0);
806     UINT_32 pipebit1 = _BIT(pipe,1);
807     UINT_32 pipebit2 = _BIT(pipe,2);
808     UINT_32 pipebit3 = _BIT(pipe,3);
809     UINT_32 elemIdx0 = _BIT(elemIdx,0);
810     UINT_32 elemIdx1 = _BIT(elemIdx,1);
811     UINT_32 elemIdx2 = _BIT(elemIdx,2);
812     UINT_32 x3 = 0;
813     UINT_32 x4 = 0;
814     UINT_32 x5 = 0;
815     UINT_32 x6 = 0;
816     UINT_32 y3 = 0;
817     UINT_32 y4 = 0;
818     UINT_32 y5 = 0;
819     UINT_32 y6 = 0;
820 
821     switch(pipeCfg)
822     {
823         case ADDR_PIPECFG_P2:
824             x4 = elemIdx2;
825             y4 = elemIdx1 ^ x4;
826             y3 = elemIdx0 ^ x4;
827             x3 = pipebit0 ^ y3;
828             *pY = Bits2Number(2, y4, y3);
829             *pX = Bits2Number(2, x4, x3);
830             break;
831         case ADDR_PIPECFG_P4_8x16:
832             x4 = elemIdx1;
833             y4 = elemIdx0 ^ x4;
834             x3 = pipebit1 ^ y4;
835             y3 = pipebit0 ^ x4;
836             *pY = Bits2Number(2, y4, y3);
837             *pX = Bits2Number(2, x4, x3);
838             break;
839         case ADDR_PIPECFG_P4_16x16:
840             x4 = elemIdx1;
841             y3 = elemIdx0 ^ x4;
842             y4 = pipebit1 ^ x4;
843             x3 = pipebit0 ^ y3 ^ x4;
844             *pY = Bits2Number(2, y4, y3);
845             *pX = Bits2Number(2, x4, x3);
846             break;
847         case ADDR_PIPECFG_P4_16x32:
848             x3 = elemIdx0 ^ pipebit0;
849             y5 = _BIT(y,5);
850             x4 = pipebit1 ^ y5;
851             y3 = pipebit0 ^ x3 ^ x4;
852             y4 = elemIdx1 ^ x4;
853             *pY = Bits2Number(2, y4, y3);
854             *pX = Bits2Number(2, x4, x3);
855             break;
856         case ADDR_PIPECFG_P4_32x32:
857             x4 = elemIdx2;
858             y3 = elemIdx0 ^ x4;
859             y4 = elemIdx1 ^ x4;
860             if((pitchInMacroTile % 2) == 0)
861             {   //even
862                 y5 = _BIT(y,5);
863                 x5 = pipebit1 ^ y5;
864                 x3 = pipebit0 ^ y3 ^ x5;
865                 *pY = Bits2Number(2, y4, y3);
866                 *pX = Bits2Number(3, x5, x4, x3);
867             }
868             else
869             {   //odd
870                 x5 = _BIT(x,5);
871                 x3 = pipebit0 ^ y3 ^ x5;
872                 *pY = Bits2Number(2, y4, y3);
873                 *pX = Bits2Number(2, x4, x3);
874             }
875             break;
876         case ADDR_PIPECFG_P8_16x16_8x16:
877             x4 = elemIdx0;
878             y5 = _BIT(y,5);
879             x5 = _BIT(x,5);
880             x3 = pipebit1 ^ y5;
881             y4 = pipebit2 ^ x4;
882             y3 = pipebit0 ^ x5 ^ x4;
883             *pY = Bits2Number(2, y4, y3);
884             *pX = Bits2Number(2, x4, x3);
885             break;
886         case ADDR_PIPECFG_P8_16x32_8x16:
887             x3 = elemIdx0;
888             y4 = pipebit1 ^ x3;
889             y5 = _BIT(y,5);
890             x5 = _BIT(x,5);
891             x4 = pipebit2 ^ y5;
892             y3 = pipebit0 ^ x4 ^ x5;
893             *pY = Bits2Number(2, y4, y3);
894             *pX = Bits2Number(2, x4, x3);
895             break;
896         case ADDR_PIPECFG_P8_32x32_8x16:
897             x4 = elemIdx1;
898             y4 = elemIdx0 ^ x4;
899             x3 = pipebit1 ^ y4;
900             if((pitchInMacroTile % 2) == 0)
901             {  //even
902                 y5 = _BIT(y,5);
903                 x5 = _BIT(x,5);
904                 x5 = pipebit2 ^ y5;
905                 y3 = pipebit0 ^ x4 ^ x5;
906                 *pY = Bits2Number(2, y4, y3);
907                 *pX = Bits2Number(3, x5, x4, x3);
908             }
909             else
910             {  //odd
911                 x5 = _BIT(x,5);
912                 y3 = pipebit0 ^ x4 ^ x5;
913                 *pY = Bits2Number(2, y4, y3);
914                 *pX = Bits2Number(2, x4, x3);
915             }
916             break;
917         case ADDR_PIPECFG_P8_16x32_16x16:
918             x3 = elemIdx0;
919             x5 = _BIT(x,5);
920             y5 = _BIT(y,5);
921             x4 = pipebit2 ^ y5;
922             y4 = pipebit1 ^ x5;
923             y3 = pipebit0 ^ x3 ^ x4;
924             *pY = Bits2Number(2, y4, y3);
925             *pX = Bits2Number(2, x4, x3);
926             break;
927         case ADDR_PIPECFG_P8_32x32_16x16:
928             x4 = elemIdx1;
929             y3 = elemIdx0 ^ x4;
930             x3 = y3^x4^pipebit0;
931             y4 = pipebit1 ^ x4;
932             if((pitchInMacroTile % 2) == 0)
933             {   //even
934                 y5 = _BIT(y,5);
935                 x5 = pipebit2 ^ y5;
936                 *pY = Bits2Number(2, y4, y3);
937                 *pX = Bits2Number(3, x5, x4, x3);
938             }
939             else
940             {   //odd
941                 *pY = Bits2Number(2, y4, y3);
942                 *pX = Bits2Number(2, x4, x3);
943             }
944             break;
945         case ADDR_PIPECFG_P8_32x32_16x32:
946             if((pitchInMacroTile % 2) == 0)
947             {   //even
948                 y5 = _BIT(y,5);
949                 y6 = _BIT(y,6);
950                 x4 = pipebit1 ^ y6;
951                 y3 = elemIdx0 ^ x4;
952                 y4 = elemIdx1 ^ x4;
953                 x3 = pipebit0 ^ y3 ^ x4;
954                 x5 = pipebit2 ^ y5;
955                 *pY = Bits2Number(2, y4, y3);
956                 *pX = Bits2Number(3, x5, x4, x3);
957             }
958             else
959             {   //odd
960                 y6 = _BIT(y,6);
961                 x4 = pipebit1 ^ y6;
962                 y3 = elemIdx0 ^ x4;
963                 y4 = elemIdx1 ^ x4;
964                 x3 = pipebit0 ^ y3 ^ x4;
965                 *pY = Bits2Number(2, y4, y3);
966                 *pX = Bits2Number(2, x4, x3);
967             }
968             break;
969         case ADDR_PIPECFG_P8_32x64_32x32:
970             x4 = elemIdx2;
971             y3 = elemIdx0 ^ x4;
972             y4 = elemIdx1 ^ x4;
973             if((pitchInMacroTile % 4) == 0)
974             {   //multiple of 4
975                 y5 = _BIT(y,5);
976                 y6 = _BIT(y,6);
977                 x5 = pipebit2 ^ y6;
978                 x6 = pipebit1 ^ y5;
979                 x3 = pipebit0 ^ y3 ^ x5;
980                 *pY = Bits2Number(2, y4, y3);
981                 *pX = Bits2Number(4, x6, x5, x4, x3);
982             }
983             else
984             {
985                 y6 = _BIT(y,6);
986                 x5 = pipebit2 ^ y6;
987                 x3 = pipebit0 ^ y3 ^ x5;
988                 *pY = Bits2Number(2, y4, y3);
989                 *pX = Bits2Number(3, x5, x4, x3);
990             }
991             break;
992         case ADDR_PIPECFG_P16_32x32_8x16:
993             x4 = elemIdx1;
994             y4 = elemIdx0 ^ x4;
995             y3 = pipebit0 ^ x4;
996             x3 = pipebit1 ^ y4;
997             if((pitchInMacroTile % 4) == 0)
998             {   //multiple of 4
999                 y5 = _BIT(y,5);
1000                 y6 = _BIT(y,6);
1001                 x5 = pipebit2 ^ y6;
1002                 x6 = pipebit3 ^ y5;
1003                 *pY = Bits2Number(2, y4, y3);
1004                 *pX = Bits2Number(4, x6, x5,x4, x3);
1005             }
1006             else
1007             {
1008                 y6 = _BIT(y,6);
1009                 x5 = pipebit2 ^ y6;
1010                 *pY = Bits2Number(2, y4, y3);
1011                 *pX = Bits2Number(3, x5, x4, x3);
1012             }
1013             break;
1014         case ADDR_PIPECFG_P16_32x32_16x16:
1015             x4 = elemIdx1;
1016             y3 = elemIdx0 ^ x4;
1017             y4 = pipebit1 ^ x4;
1018             x3 = pipebit0 ^ y3 ^ x4;
1019             if((pitchInMacroTile % 4) == 0)
1020             {   //multiple of 4
1021                 y5 = _BIT(y,5);
1022                 y6 = _BIT(y,6);
1023                 x5 = pipebit2 ^ y6;
1024                 x6 = pipebit3 ^ y5;
1025                 *pY = Bits2Number(2, y4, y3);
1026                 *pX = Bits2Number(4, x6, x5, x4, x3);
1027             }
1028             else
1029             {
1030                 y6 = _BIT(y,6);
1031                 x5 = pipebit2 ^ y6;
1032                 *pY = Bits2Number(2, y4, y3);
1033                 *pX = Bits2Number(3, x5, x4, x3);
1034             }
1035             break;
1036         default:
1037             ADDR_UNHANDLED_CASE();
1038     }
1039 }
1040 
1041 /**
1042 ****************************************************************************************************
1043 *   SiLib::TileCoordToMaskElementIndex
1044 *
1045 *   @brief
1046 *       Compute element index from coordinates in tiles
1047 *   @return
1048 *       Element index
1049 ****************************************************************************************************
1050 */
TileCoordToMaskElementIndex(UINT_32 tx,UINT_32 ty,AddrPipeCfg pipeConfig,UINT_32 * macroShift,UINT_32 * elemIdxBits) const1051 UINT_32 SiLib::TileCoordToMaskElementIndex(
1052     UINT_32         tx,                 ///< [in] x coord, in Tiles
1053     UINT_32         ty,                 ///< [in] y coord, in Tiles
1054     AddrPipeCfg     pipeConfig,         ///< [in] pipe config
1055     UINT_32*        macroShift,         ///< [out] macro shift
1056     UINT_32*        elemIdxBits         ///< [out] tile offset bits
1057     ) const
1058 {
1059     UINT_32 elemIdx = 0;
1060     UINT_32 elemIdx0, elemIdx1, elemIdx2;
1061     UINT_32 tx0, tx1;
1062     UINT_32 ty0, ty1;
1063 
1064     tx0 = _BIT(tx,0);
1065     tx1 = _BIT(tx,1);
1066     ty0 = _BIT(ty,0);
1067     ty1 = _BIT(ty,1);
1068 
1069     switch(pipeConfig)
1070     {
1071         case ADDR_PIPECFG_P2:
1072             *macroShift = 3;
1073             *elemIdxBits =3;
1074             elemIdx2 = tx1;
1075             elemIdx1 = tx1 ^ ty1;
1076             elemIdx0 = tx1 ^ ty0;
1077             elemIdx = Bits2Number(3,elemIdx2,elemIdx1,elemIdx0);
1078             break;
1079         case ADDR_PIPECFG_P4_8x16:
1080             *macroShift = 2;
1081             *elemIdxBits =2;
1082             elemIdx1 = tx1;
1083             elemIdx0 = tx1 ^ ty1;
1084             elemIdx = Bits2Number(2,elemIdx1,elemIdx0);
1085             break;
1086         case ADDR_PIPECFG_P4_16x16:
1087             *macroShift = 2;
1088             *elemIdxBits =2;
1089             elemIdx0 = tx1^ty0;
1090             elemIdx1 = tx1;
1091             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1092             break;
1093         case ADDR_PIPECFG_P4_16x32:
1094             *macroShift = 2;
1095             *elemIdxBits =2;
1096             elemIdx0 = tx1^ty0;
1097             elemIdx1 = tx1^ty1;
1098             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1099             break;
1100         case ADDR_PIPECFG_P4_32x32:
1101             *macroShift = 2;
1102             *elemIdxBits =3;
1103             elemIdx0 = tx1^ty0;
1104             elemIdx1 = tx1^ty1;
1105             elemIdx2 = tx1;
1106             elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0);
1107             break;
1108         case ADDR_PIPECFG_P8_16x16_8x16:
1109             *macroShift = 1;
1110             *elemIdxBits =1;
1111             elemIdx0 = tx1;
1112             elemIdx = elemIdx0;
1113             break;
1114         case ADDR_PIPECFG_P8_16x32_8x16:
1115             *macroShift = 1;
1116             *elemIdxBits =1;
1117             elemIdx0 = tx0;
1118             elemIdx = elemIdx0;
1119             break;
1120         case ADDR_PIPECFG_P8_32x32_8x16:
1121             *macroShift = 1;
1122             *elemIdxBits =2;
1123             elemIdx1 = tx1;
1124             elemIdx0 = tx1^ty1;
1125             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1126             break;
1127         case ADDR_PIPECFG_P8_16x32_16x16:
1128             *macroShift = 1;
1129             *elemIdxBits =1;
1130             elemIdx0 = tx0;
1131             elemIdx = elemIdx0;
1132             break;
1133         case ADDR_PIPECFG_P8_32x32_16x16:
1134             *macroShift = 1;
1135             *elemIdxBits =2;
1136             elemIdx0 = tx1^ty0;
1137             elemIdx1 = tx1;
1138             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1139             break;
1140         case ADDR_PIPECFG_P8_32x32_16x32:
1141             *macroShift = 1;
1142             *elemIdxBits =2;
1143             elemIdx0 =  tx1^ty0;
1144             elemIdx1 = tx1^ty1;
1145             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1146             break;
1147         case ADDR_PIPECFG_P8_32x64_32x32:
1148             *macroShift = 1;
1149             *elemIdxBits =3;
1150             elemIdx0 = tx1^ty0;
1151             elemIdx1 = tx1^ty1;
1152             elemIdx2 = tx1;
1153             elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0);
1154             break;
1155         case ADDR_PIPECFG_P16_32x32_8x16:
1156             *macroShift = 0;
1157             *elemIdxBits =2;
1158             elemIdx0 = tx1^ty1;
1159             elemIdx1 = tx1;
1160             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1161             break;
1162         case ADDR_PIPECFG_P16_32x32_16x16:
1163             *macroShift = 0;
1164             *elemIdxBits =2;
1165             elemIdx0 = tx1^ty0;
1166             elemIdx1 = tx1;
1167             elemIdx = Bits2Number(2, elemIdx1, elemIdx0);
1168             break;
1169         default:
1170             ADDR_UNHANDLED_CASE();
1171             break;
1172     }
1173 
1174     return elemIdx;
1175 }
1176 
1177 /**
1178 ****************************************************************************************************
1179 *   SiLib::HwlComputeTileDataWidthAndHeightLinear
1180 *
1181 *   @brief
1182 *       Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout
1183 *
1184 *   @return
1185 *       N/A
1186 *
1187 *   @note
1188 *       MacroWidth and macroHeight are measured in pixels
1189 ****************************************************************************************************
1190 */
HwlComputeTileDataWidthAndHeightLinear(UINT_32 * pMacroWidth,UINT_32 * pMacroHeight,UINT_32 bpp,ADDR_TILEINFO * pTileInfo) const1191 VOID SiLib::HwlComputeTileDataWidthAndHeightLinear(
1192     UINT_32*        pMacroWidth,     ///< [out] macro tile width
1193     UINT_32*        pMacroHeight,    ///< [out] macro tile height
1194     UINT_32         bpp,             ///< [in] bits per pixel
1195     ADDR_TILEINFO*  pTileInfo        ///< [in] tile info
1196     ) const
1197 {
1198     ADDR_ASSERT(pTileInfo != NULL);
1199     UINT_32 macroWidth;
1200     UINT_32 macroHeight;
1201 
1202     /// In linear mode, the htile or cmask buffer must be padded out to 4 tiles
1203     /// but for P8_32x64_32x32, it must be padded out to 8 tiles
1204     /// Actually there are more pipe configs which need 8-tile padding but SI family
1205     /// has a bug which is fixed in CI family
1206     if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32) ||
1207         (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) ||
1208         (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x32_16x16))
1209     {
1210         macroWidth  = 8*MicroTileWidth;
1211         macroHeight = 8*MicroTileHeight;
1212     }
1213     else
1214     {
1215         macroWidth  = 4*MicroTileWidth;
1216         macroHeight = 4*MicroTileHeight;
1217     }
1218 
1219     *pMacroWidth    = macroWidth;
1220     *pMacroHeight   = macroHeight;
1221 }
1222 
1223 /**
1224 ****************************************************************************************************
1225 *   SiLib::HwlComputeHtileBytes
1226 *
1227 *   @brief
1228 *       Compute htile size in bytes
1229 *
1230 *   @return
1231 *       Htile size in bytes
1232 ****************************************************************************************************
1233 */
HwlComputeHtileBytes(UINT_32 pitch,UINT_32 height,UINT_32 bpp,BOOL_32 isLinear,UINT_32 numSlices,UINT_64 * pSliceBytes,UINT_32 baseAlign) const1234 UINT_64 SiLib::HwlComputeHtileBytes(
1235     UINT_32     pitch,          ///< [in] pitch
1236     UINT_32     height,         ///< [in] height
1237     UINT_32     bpp,            ///< [in] bits per pixel
1238     BOOL_32     isLinear,       ///< [in] if it is linear mode
1239     UINT_32     numSlices,      ///< [in] number of slices
1240     UINT_64*    pSliceBytes,    ///< [out] bytes per slice
1241     UINT_32     baseAlign       ///< [in] base alignments
1242     ) const
1243 {
1244     return ComputeHtileBytes(pitch, height, bpp, isLinear, numSlices, pSliceBytes, baseAlign);
1245 }
1246 
1247 /**
1248 ****************************************************************************************************
1249 *   SiLib::HwlComputeXmaskAddrFromCoord
1250 *
1251 *   @brief
1252 *       Compute address from coordinates for htile/cmask
1253 *   @return
1254 *       Byte address
1255 ****************************************************************************************************
1256 */
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) const1257 UINT_64 SiLib::HwlComputeXmaskAddrFromCoord(
1258     UINT_32        pitch,          ///< [in] pitch
1259     UINT_32        height,         ///< [in] height
1260     UINT_32        x,              ///< [in] x coord
1261     UINT_32        y,              ///< [in] y coord
1262     UINT_32        slice,          ///< [in] slice/depth index
1263     UINT_32        numSlices,      ///< [in] number of slices
1264     UINT_32        factor,         ///< [in] factor that indicates cmask(2) or htile(1)
1265     BOOL_32        isLinear,       ///< [in] linear or tiled HTILE layout
1266     BOOL_32        isWidth8,       ///< [in] TRUE if width is 8, FALSE means 4. It's register value
1267     BOOL_32        isHeight8,      ///< [in] TRUE if width is 8, FALSE means 4. It's register value
1268     ADDR_TILEINFO* pTileInfo,      ///< [in] Tile info
1269     UINT_32*       pBitPosition    ///< [out] bit position inside a byte
1270     ) const
1271 {
1272     UINT_32 tx = x / MicroTileWidth;
1273     UINT_32 ty = y / MicroTileHeight;
1274     UINT_32 newPitch;
1275     UINT_32 newHeight;
1276     UINT_64 totalBytes;
1277     UINT_32 macroWidth;
1278     UINT_32 macroHeight;
1279     UINT_64 pSliceBytes;
1280     UINT_32 pBaseAlign;
1281     UINT_32 tileNumPerPipe;
1282     UINT_32 elemBits;
1283 
1284     if (factor == 2) //CMASK
1285     {
1286         ADDR_CMASK_FLAGS flags = {{0}};
1287 
1288         tileNumPerPipe = 256;
1289 
1290         ComputeCmaskInfo(flags,
1291                          pitch,
1292                          height,
1293                          numSlices,
1294                          isLinear,
1295                          pTileInfo,
1296                          &newPitch,
1297                          &newHeight,
1298                          &totalBytes,
1299                          &macroWidth,
1300                          &macroHeight);
1301         elemBits = CmaskElemBits;
1302     }
1303     else //HTile
1304     {
1305         ADDR_HTILE_FLAGS flags = {{0}};
1306 
1307         tileNumPerPipe = 512;
1308 
1309         ComputeHtileInfo(flags,
1310                          pitch,
1311                          height,
1312                          numSlices,
1313                          isLinear,
1314                          TRUE,
1315                          TRUE,
1316                          pTileInfo,
1317                          &newPitch,
1318                          &newHeight,
1319                          &totalBytes,
1320                          &macroWidth,
1321                          &macroHeight,
1322                          &pSliceBytes,
1323                          &pBaseAlign);
1324         elemBits = 32;
1325     }
1326 
1327     const UINT_32 pitchInTile = newPitch / MicroTileWidth;
1328     const UINT_32 heightInTile = newHeight / MicroTileWidth;
1329     UINT_64 macroOffset; // Per pipe starting offset of the macro tile in which this tile lies.
1330     UINT_64 microNumber; // Per pipe starting offset of the macro tile in which this tile lies.
1331     UINT_32 microX;
1332     UINT_32 microY;
1333     UINT_64 microOffset;
1334     UINT_32 microShift;
1335     UINT_64 totalOffset;
1336     UINT_32 elemIdxBits;
1337     UINT_32 elemIdx =
1338         TileCoordToMaskElementIndex(tx, ty, pTileInfo->pipeConfig, &microShift, &elemIdxBits);
1339 
1340     UINT_32 numPipes = HwlGetPipes(pTileInfo);
1341 
1342     if (isLinear)
1343     {   //linear addressing
1344         // Linear addressing is extremelly wasting memory if slice > 1, since each pipe has the full
1345         // slice memory foot print instead of divided by numPipes.
1346         microX = tx / 4; // Macro Tile is 4x4
1347         microY = ty / 4 ;
1348         microNumber = static_cast<UINT_64>(microX + microY * (pitchInTile / 4)) << microShift;
1349 
1350         UINT_32 sliceBits = pitchInTile * heightInTile;
1351 
1352         // do htile single slice alignment if the flag is true
1353         if (m_configFlags.useHtileSliceAlign && (factor == 1))  //Htile
1354         {
1355             sliceBits = PowTwoAlign(sliceBits, BITS_TO_BYTES(HtileCacheBits) * numPipes / elemBits);
1356         }
1357         macroOffset = slice * (sliceBits / numPipes) * elemBits ;
1358     }
1359     else
1360     {   //tiled addressing
1361         const UINT_32 macroWidthInTile = macroWidth / MicroTileWidth; // Now in unit of Tiles
1362         const UINT_32 macroHeightInTile = macroHeight / MicroTileHeight;
1363         const UINT_32 pitchInCL = pitchInTile / macroWidthInTile;
1364         const UINT_32 heightInCL = heightInTile / macroHeightInTile;
1365 
1366         const UINT_32 macroX = x / macroWidth;
1367         const UINT_32 macroY = y / macroHeight;
1368         const UINT_32 macroNumber = macroX + macroY * pitchInCL + slice * pitchInCL * heightInCL;
1369 
1370         // Per pipe starting offset of the cache line in which this tile lies.
1371         microX = (x % macroWidth) / MicroTileWidth / 4; // Macro Tile is 4x4
1372         microY = (y % macroHeight) / MicroTileHeight / 4 ;
1373         microNumber = static_cast<UINT_64>(microX + microY * (macroWidth / MicroTileWidth / 4)) << microShift;
1374 
1375         macroOffset = macroNumber * tileNumPerPipe * elemBits;
1376     }
1377 
1378     if(elemIdxBits == microShift)
1379     {
1380         microNumber += elemIdx;
1381     }
1382     else
1383     {
1384         microNumber >>= elemIdxBits;
1385         microNumber <<= elemIdxBits;
1386         microNumber += elemIdx;
1387     }
1388 
1389     microOffset = elemBits * microNumber;
1390     totalOffset = microOffset + macroOffset;
1391 
1392     UINT_32 pipe = ComputePipeFromCoord(x, y, 0, ADDR_TM_2D_TILED_THIN1, 0, FALSE, pTileInfo);
1393     UINT_64 addrInBits = totalOffset % (m_pipeInterleaveBytes * 8) +
1394                    pipe * (m_pipeInterleaveBytes * 8) +
1395                    totalOffset / (m_pipeInterleaveBytes * 8) * (m_pipeInterleaveBytes * 8) * numPipes;
1396     *pBitPosition = static_cast<UINT_32>(addrInBits) % 8;
1397     UINT_64 addr = addrInBits / 8;
1398 
1399     return addr;
1400 }
1401 
1402 /**
1403 ****************************************************************************************************
1404 *   SiLib::HwlComputeXmaskCoordFromAddr
1405 *
1406 *   @brief
1407 *       Compute the coord from an address of a cmask/htile
1408 *
1409 *   @return
1410 *       N/A
1411 *
1412 *   @note
1413 *       This method is reused by htile, so rename to Xmask
1414 ****************************************************************************************************
1415 */
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) const1416 VOID SiLib::HwlComputeXmaskCoordFromAddr(
1417     UINT_64         addr,           ///< [in] address
1418     UINT_32         bitPosition,    ///< [in] bitPosition in a byte
1419     UINT_32         pitch,          ///< [in] pitch
1420     UINT_32         height,         ///< [in] height
1421     UINT_32         numSlices,      ///< [in] number of slices
1422     UINT_32         factor,         ///< [in] factor that indicates cmask or htile
1423     BOOL_32         isLinear,       ///< [in] linear or tiled HTILE layout
1424     BOOL_32         isWidth8,       ///< [in] Not used by SI
1425     BOOL_32         isHeight8,      ///< [in] Not used by SI
1426     ADDR_TILEINFO*  pTileInfo,      ///< [in] Tile info
1427     UINT_32*        pX,             ///< [out] x coord
1428     UINT_32*        pY,             ///< [out] y coord
1429     UINT_32*        pSlice          ///< [out] slice index
1430     ) const
1431 {
1432     UINT_32 newPitch;
1433     UINT_32 newHeight;
1434     UINT_64 totalBytes;
1435     UINT_32 clWidth;
1436     UINT_32 clHeight;
1437     UINT_32 tileNumPerPipe;
1438     UINT_64 sliceBytes;
1439 
1440     *pX = 0;
1441     *pY = 0;
1442     *pSlice = 0;
1443 
1444     if (factor == 2) //CMASK
1445     {
1446         ADDR_CMASK_FLAGS flags = {{0}};
1447 
1448         tileNumPerPipe = 256;
1449 
1450         ComputeCmaskInfo(flags,
1451                          pitch,
1452                          height,
1453                          numSlices,
1454                          isLinear,
1455                          pTileInfo,
1456                          &newPitch,
1457                          &newHeight,
1458                          &totalBytes,
1459                          &clWidth,
1460                          &clHeight);
1461     }
1462     else //HTile
1463     {
1464         ADDR_HTILE_FLAGS flags = {{0}};
1465 
1466         tileNumPerPipe = 512;
1467 
1468         ComputeHtileInfo(flags,
1469                          pitch,
1470                          height,
1471                          numSlices,
1472                          isLinear,
1473                          TRUE,
1474                          TRUE,
1475                          pTileInfo,
1476                          &newPitch,
1477                          &newHeight,
1478                          &totalBytes,
1479                          &clWidth,
1480                          &clHeight,
1481                          &sliceBytes);
1482     }
1483 
1484     const UINT_32 pitchInTile = newPitch / MicroTileWidth;
1485     const UINT_32 heightInTile = newHeight / MicroTileWidth;
1486     const UINT_32 pitchInMacroTile = pitchInTile / 4;
1487     UINT_32 macroShift;
1488     UINT_32 elemIdxBits;
1489     // get macroShift and elemIdxBits
1490     TileCoordToMaskElementIndex(0, 0, pTileInfo->pipeConfig, &macroShift, &elemIdxBits);
1491 
1492     const UINT_32 numPipes = HwlGetPipes(pTileInfo);
1493     const UINT_32 pipe = (UINT_32)((addr / m_pipeInterleaveBytes) % numPipes);
1494     // per pipe
1495     UINT_64 localOffset = (addr % m_pipeInterleaveBytes) +
1496         (addr / m_pipeInterleaveBytes / numPipes)* m_pipeInterleaveBytes;
1497 
1498     UINT_32 tileIndex;
1499     if (factor == 2) //CMASK
1500     {
1501         tileIndex = (UINT_32)(localOffset * 2 + (bitPosition != 0));
1502     }
1503     else
1504     {
1505         tileIndex = (UINT_32)(localOffset / 4);
1506     }
1507 
1508     UINT_32 macroOffset;
1509     if (isLinear)
1510     {
1511         UINT_32 sliceSizeInTile = pitchInTile * heightInTile;
1512 
1513         // do htile single slice alignment if the flag is true
1514         if (m_configFlags.useHtileSliceAlign && (factor == 1))  //Htile
1515         {
1516             sliceSizeInTile = PowTwoAlign(sliceSizeInTile, static_cast<UINT_32>(sliceBytes) / 64);
1517         }
1518         *pSlice = tileIndex / (sliceSizeInTile / numPipes);
1519         macroOffset = tileIndex % (sliceSizeInTile / numPipes);
1520     }
1521     else
1522     {
1523         const UINT_32 clWidthInTile = clWidth / MicroTileWidth; // Now in unit of Tiles
1524         const UINT_32 clHeightInTile = clHeight / MicroTileHeight;
1525         const UINT_32 pitchInCL = pitchInTile / clWidthInTile;
1526         const UINT_32 heightInCL = heightInTile / clHeightInTile;
1527         const UINT_32 clIndex = tileIndex / tileNumPerPipe;
1528 
1529         UINT_32 clX = clIndex % pitchInCL;
1530         UINT_32 clY = (clIndex % (heightInCL * pitchInCL)) / pitchInCL;
1531 
1532         *pX = clX * clWidthInTile * MicroTileWidth;
1533         *pY = clY * clHeightInTile * MicroTileHeight;
1534         *pSlice = clIndex / (heightInCL * pitchInCL);
1535 
1536         macroOffset = tileIndex % tileNumPerPipe;
1537     }
1538 
1539     UINT_32 elemIdx = macroOffset & 7;
1540     macroOffset >>= elemIdxBits;
1541 
1542     if (elemIdxBits != macroShift)
1543     {
1544         macroOffset <<= (elemIdxBits - macroShift);
1545 
1546         UINT_32 pipebit1 = _BIT(pipe,1);
1547         UINT_32 pipebit2 = _BIT(pipe,2);
1548         UINT_32 pipebit3 = _BIT(pipe,3);
1549         if (pitchInMacroTile % 2)
1550         {   //odd
1551             switch (pTileInfo->pipeConfig)
1552             {
1553                 case ADDR_PIPECFG_P4_32x32:
1554                     macroOffset |= pipebit1;
1555                     break;
1556                 case ADDR_PIPECFG_P8_32x32_8x16:
1557                 case ADDR_PIPECFG_P8_32x32_16x16:
1558                 case ADDR_PIPECFG_P8_32x32_16x32:
1559                     macroOffset |= pipebit2;
1560                     break;
1561                 default:
1562                     break;
1563             }
1564 
1565         }
1566 
1567         if (pitchInMacroTile % 4)
1568         {
1569             if (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)
1570             {
1571                 macroOffset |= (pipebit1<<1);
1572             }
1573             if((pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) ||
1574                (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_16x16))
1575             {
1576                 macroOffset |= (pipebit3<<1);
1577             }
1578         }
1579     }
1580 
1581     UINT_32 macroX;
1582     UINT_32 macroY;
1583 
1584     if (isLinear)
1585     {
1586         macroX = macroOffset % pitchInMacroTile;
1587         macroY = macroOffset / pitchInMacroTile;
1588     }
1589     else
1590     {
1591         const UINT_32 clWidthInMacroTile = clWidth / (MicroTileWidth * 4);
1592         macroX = macroOffset % clWidthInMacroTile;
1593         macroY = macroOffset / clWidthInMacroTile;
1594     }
1595 
1596     *pX += macroX * 4 * MicroTileWidth;
1597     *pY += macroY * 4 * MicroTileHeight;
1598 
1599     UINT_32 microX;
1600     UINT_32 microY;
1601     ComputeTileCoordFromPipeAndElemIdx(elemIdx, pipe, pTileInfo->pipeConfig, pitchInMacroTile,
1602                                        *pX, *pY, &microX, &microY);
1603 
1604     *pX += microX * MicroTileWidth;
1605     *pY += microY * MicroTileWidth;
1606 }
1607 
1608 /**
1609 ****************************************************************************************************
1610 *   SiLib::HwlGetPitchAlignmentLinear
1611 *   @brief
1612 *       Get pitch alignment
1613 *   @return
1614 *       pitch alignment
1615 ****************************************************************************************************
1616 */
HwlGetPitchAlignmentLinear(UINT_32 bpp,ADDR_SURFACE_FLAGS flags) const1617 UINT_32 SiLib::HwlGetPitchAlignmentLinear(
1618     UINT_32             bpp,    ///< [in] bits per pixel
1619     ADDR_SURFACE_FLAGS  flags   ///< [in] surface flags
1620     ) const
1621 {
1622     UINT_32 pitchAlign;
1623 
1624     // Interleaved access requires a 256B aligned pitch, so fall back to pre-SI alignment
1625     if (flags.interleaved)
1626     {
1627         pitchAlign = Max(64u, m_pipeInterleaveBytes / BITS_TO_BYTES(bpp));
1628 
1629     }
1630     else
1631     {
1632         pitchAlign = Max(8u, 64 / BITS_TO_BYTES(bpp));
1633     }
1634 
1635     return pitchAlign;
1636 }
1637 
1638 /**
1639 ****************************************************************************************************
1640 *   SiLib::HwlGetSizeAdjustmentLinear
1641 *
1642 *   @brief
1643 *       Adjust linear surface pitch and slice size
1644 *
1645 *   @return
1646 *       Logical slice size in bytes
1647 ****************************************************************************************************
1648 */
HwlGetSizeAdjustmentLinear(AddrTileMode tileMode,UINT_32 bpp,UINT_32 numSamples,UINT_32 baseAlign,UINT_32 pitchAlign,UINT_32 * pPitch,UINT_32 * pHeight,UINT_32 * pHeightAlign) const1649 UINT_64 SiLib::HwlGetSizeAdjustmentLinear(
1650     AddrTileMode        tileMode,       ///< [in] tile mode
1651     UINT_32             bpp,            ///< [in] bits per pixel
1652     UINT_32             numSamples,     ///< [in] number of samples
1653     UINT_32             baseAlign,      ///< [in] base alignment
1654     UINT_32             pitchAlign,     ///< [in] pitch alignment
1655     UINT_32*            pPitch,         ///< [in,out] pointer to pitch
1656     UINT_32*            pHeight,        ///< [in,out] pointer to height
1657     UINT_32*            pHeightAlign    ///< [in,out] pointer to height align
1658     ) const
1659 {
1660     UINT_64 sliceSize;
1661     if (tileMode == ADDR_TM_LINEAR_GENERAL)
1662     {
1663         sliceSize = BITS_TO_BYTES(static_cast<UINT_64>(*pPitch) * (*pHeight) * bpp * numSamples);
1664     }
1665     else
1666     {
1667         UINT_32 pitch   = *pPitch;
1668         UINT_32 height  = *pHeight;
1669 
1670         UINT_32 pixelsPerPipeInterleave = m_pipeInterleaveBytes / BITS_TO_BYTES(bpp);
1671         UINT_32 sliceAlignInPixel = pixelsPerPipeInterleave < 64 ? 64 : pixelsPerPipeInterleave;
1672 
1673         // numSamples should be 1 in real cases (no MSAA for linear but TGL may pass non 1 value)
1674         UINT_64 pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples;
1675 
1676         while (pixelPerSlice % sliceAlignInPixel)
1677         {
1678             pitch += pitchAlign;
1679             pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples;
1680         }
1681 
1682         *pPitch = pitch;
1683 
1684         UINT_32 heightAlign = 1;
1685 
1686         while ((pitch * heightAlign) % sliceAlignInPixel)
1687         {
1688             heightAlign++;
1689         }
1690 
1691         *pHeightAlign = heightAlign;
1692 
1693         sliceSize = BITS_TO_BYTES(pixelPerSlice * bpp);
1694     }
1695 
1696     return sliceSize;
1697 }
1698 
1699 /**
1700 ****************************************************************************************************
1701 *   SiLib::HwlPreHandleBaseLvl3xPitch
1702 *
1703 *   @brief
1704 *       Pre-handler of 3x pitch (96 bit) adjustment
1705 *
1706 *   @return
1707 *       Expected pitch
1708 ****************************************************************************************************
1709 */
HwlPreHandleBaseLvl3xPitch(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,UINT_32 expPitch) const1710 UINT_32 SiLib::HwlPreHandleBaseLvl3xPitch(
1711     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,        ///< [in] input
1712     UINT_32                                 expPitch    ///< [in] pitch
1713     ) const
1714 {
1715     ADDR_ASSERT(pIn->width == expPitch);
1716 
1717     // From SI, if pow2Pad is 1 the pitch is expanded 3x first, then padded to pow2, so nothing to
1718     // do here
1719     if (pIn->flags.pow2Pad == FALSE)
1720     {
1721         Addr::V1::Lib::HwlPreHandleBaseLvl3xPitch(pIn, expPitch);
1722     }
1723     else
1724     {
1725         ADDR_ASSERT(IsPow2(expPitch));
1726     }
1727 
1728     return expPitch;
1729 }
1730 
1731 /**
1732 ****************************************************************************************************
1733 *   SiLib::HwlPostHandleBaseLvl3xPitch
1734 *
1735 *   @brief
1736 *       Post-handler of 3x pitch adjustment
1737 *
1738 *   @return
1739 *       Expected pitch
1740 ****************************************************************************************************
1741 */
HwlPostHandleBaseLvl3xPitch(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,UINT_32 expPitch) const1742 UINT_32 SiLib::HwlPostHandleBaseLvl3xPitch(
1743     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,        ///< [in] input
1744     UINT_32                                 expPitch    ///< [in] pitch
1745     ) const
1746 {
1747     /**
1748      * @note The pitch will be divided by 3 in the end so the value will look odd but h/w should
1749      *  be able to compute a correct pitch from it as h/w address library is doing the job.
1750      */
1751     // From SI, the pitch is expanded 3x first, then padded to pow2, so no special handler here
1752     if (pIn->flags.pow2Pad == FALSE)
1753     {
1754         Addr::V1::Lib::HwlPostHandleBaseLvl3xPitch(pIn, expPitch);
1755     }
1756 
1757     return expPitch;
1758 }
1759 
1760 /**
1761 ****************************************************************************************************
1762 *   SiLib::HwlGetPitchAlignmentMicroTiled
1763 *
1764 *   @brief
1765 *       Compute 1D tiled surface pitch alignment
1766 *
1767 *   @return
1768 *       pitch alignment
1769 ****************************************************************************************************
1770 */
HwlGetPitchAlignmentMicroTiled(AddrTileMode tileMode,UINT_32 bpp,ADDR_SURFACE_FLAGS flags,UINT_32 numSamples) const1771 UINT_32 SiLib::HwlGetPitchAlignmentMicroTiled(
1772     AddrTileMode        tileMode,          ///< [in] tile mode
1773     UINT_32             bpp,               ///< [in] bits per pixel
1774     ADDR_SURFACE_FLAGS  flags,             ///< [in] surface flags
1775     UINT_32             numSamples         ///< [in] number of samples
1776     ) const
1777 {
1778     UINT_32 pitchAlign;
1779 
1780     if (flags.qbStereo)
1781     {
1782         pitchAlign = EgBasedLib::HwlGetPitchAlignmentMicroTiled(tileMode,bpp,flags,numSamples);
1783     }
1784     else
1785     {
1786         pitchAlign = 8;
1787     }
1788 
1789     return pitchAlign;
1790 }
1791 
1792 /**
1793 ****************************************************************************************************
1794 *   SiLib::HwlGetSizeAdjustmentMicroTiled
1795 *
1796 *   @brief
1797 *       Adjust 1D tiled surface pitch and slice size
1798 *
1799 *   @return
1800 *       Logical slice size in bytes
1801 ****************************************************************************************************
1802 */
HwlGetSizeAdjustmentMicroTiled(UINT_32 thickness,UINT_32 bpp,ADDR_SURFACE_FLAGS flags,UINT_32 numSamples,UINT_32 baseAlign,UINT_32 pitchAlign,UINT_32 * pPitch,UINT_32 * pHeight) const1803 UINT_64 SiLib::HwlGetSizeAdjustmentMicroTiled(
1804     UINT_32             thickness,      ///< [in] thickness
1805     UINT_32             bpp,            ///< [in] bits per pixel
1806     ADDR_SURFACE_FLAGS  flags,          ///< [in] surface flags
1807     UINT_32             numSamples,     ///< [in] number of samples
1808     UINT_32             baseAlign,      ///< [in] base alignment
1809     UINT_32             pitchAlign,     ///< [in] pitch alignment
1810     UINT_32*            pPitch,         ///< [in,out] pointer to pitch
1811     UINT_32*            pHeight         ///< [in,out] pointer to height
1812     ) const
1813 {
1814     UINT_64 logicalSliceSize;
1815     UINT_64 physicalSliceSize;
1816 
1817     UINT_32 pitch   = *pPitch;
1818     UINT_32 height  = *pHeight;
1819 
1820     // Logical slice: pitch * height * bpp * numSamples (no 1D MSAA so actually numSamples == 1)
1821     logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples);
1822 
1823     // Physical slice: multiplied by thickness
1824     physicalSliceSize =  logicalSliceSize * thickness;
1825 
1826     // Pitch alignment is always 8, so if slice size is not padded to base alignment
1827     // (pipe_interleave_size), we need to increase pitch
1828     while ((physicalSliceSize % baseAlign) != 0)
1829     {
1830         pitch += pitchAlign;
1831 
1832         logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples);
1833 
1834         physicalSliceSize =  logicalSliceSize * thickness;
1835     }
1836 
1837 #if !ALT_TEST
1838     //
1839     // Special workaround for depth/stencil buffer, use 8 bpp to align depth buffer again since
1840     // the stencil plane may have larger pitch if the slice size is smaller than base alignment.
1841     //
1842     // Note: this actually does not work for mipmap but mipmap depth texture is not really
1843     // sampled with mipmap.
1844     //
1845     if (flags.depth && (flags.noStencil == FALSE))
1846     {
1847         ADDR_ASSERT(numSamples == 1);
1848 
1849         UINT_64 logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height; // 1 byte stencil
1850 
1851         while ((logicalSiceSizeStencil % baseAlign) != 0)
1852         {
1853             pitch += pitchAlign; // Stencil plane's pitch alignment is the same as depth plane's
1854 
1855             logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height;
1856         }
1857 
1858         if (pitch != *pPitch)
1859         {
1860             // If this is a mipmap, this padded one cannot be sampled as a whole mipmap!
1861             logicalSliceSize = logicalSiceSizeStencil * BITS_TO_BYTES(bpp);
1862         }
1863     }
1864 #endif
1865     *pPitch = pitch;
1866 
1867     // No adjust for pHeight
1868 
1869     return logicalSliceSize;
1870 }
1871 
1872 /**
1873 ****************************************************************************************************
1874 *   SiLib::HwlConvertChipFamily
1875 *
1876 *   @brief
1877 *       Convert familyID defined in atiid.h to ChipFamily and set m_chipFamily/m_chipRevision
1878 *   @return
1879 *       ChipFamily
1880 ****************************************************************************************************
1881 */
HwlConvertChipFamily(UINT_32 uChipFamily,UINT_32 uChipRevision)1882 ChipFamily SiLib::HwlConvertChipFamily(
1883     UINT_32 uChipFamily,        ///< [in] chip family defined in atiih.h
1884     UINT_32 uChipRevision)      ///< [in] chip revision defined in "asic_family"_id.h
1885 {
1886     ChipFamily family = ADDR_CHIP_FAMILY_SI;
1887 
1888     switch (uChipFamily)
1889     {
1890         case FAMILY_SI:
1891             m_settings.isSouthernIsland = 1;
1892             m_settings.isTahiti     = ASICREV_IS_TAHITI_P(uChipRevision);
1893             m_settings.isPitCairn   = ASICREV_IS_PITCAIRN_PM(uChipRevision);
1894             m_settings.isCapeVerde  = ASICREV_IS_CAPEVERDE_M(uChipRevision);
1895             m_settings.isOland      = ASICREV_IS_OLAND_M(uChipRevision);
1896             m_settings.isHainan     = ASICREV_IS_HAINAN_V(uChipRevision);
1897             break;
1898         default:
1899             ADDR_ASSERT(!"This should be a Fusion");
1900             break;
1901     }
1902 
1903     return family;
1904 }
1905 
1906 /**
1907 ****************************************************************************************************
1908 *   SiLib::HwlSetupTileInfo
1909 *
1910 *   @brief
1911 *       Setup default value of tile info for SI
1912 ****************************************************************************************************
1913 */
HwlSetupTileInfo(AddrTileMode tileMode,ADDR_SURFACE_FLAGS flags,UINT_32 bpp,UINT_32 pitch,UINT_32 height,UINT_32 numSamples,ADDR_TILEINFO * pTileInfoIn,ADDR_TILEINFO * pTileInfoOut,AddrTileType inTileType,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const1914 VOID SiLib::HwlSetupTileInfo(
1915     AddrTileMode                        tileMode,       ///< [in] Tile mode
1916     ADDR_SURFACE_FLAGS                  flags,          ///< [in] Surface type flags
1917     UINT_32                             bpp,            ///< [in] Bits per pixel
1918     UINT_32                             pitch,          ///< [in] Pitch in pixels
1919     UINT_32                             height,         ///< [in] Height in pixels
1920     UINT_32                             numSamples,     ///< [in] Number of samples
1921     ADDR_TILEINFO*                      pTileInfoIn,    ///< [in] Tile info input: NULL for default
1922     ADDR_TILEINFO*                      pTileInfoOut,   ///< [out] Tile info output
1923     AddrTileType                        inTileType,     ///< [in] Tile type
1924     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*   pOut            ///< [out] Output
1925     ) const
1926 {
1927     UINT_32 thickness = Thickness(tileMode);
1928     ADDR_TILEINFO* pTileInfo = pTileInfoOut;
1929     INT index = TileIndexInvalid;
1930 
1931     // Fail-safe code
1932     if (IsLinear(tileMode) == FALSE)
1933     {
1934         // 128 bpp/thick tiling must be non-displayable.
1935         // Fmask reuse color buffer's entry but bank-height field can be from another entry
1936         // To simplify the logic, fmask entry should be picked from non-displayable ones
1937         if (bpp == 128 || thickness > 1 || flags.fmask || flags.prt)
1938         {
1939             inTileType = ADDR_NON_DISPLAYABLE;
1940         }
1941 
1942         if (flags.depth || flags.stencil)
1943         {
1944             inTileType = ADDR_DEPTH_SAMPLE_ORDER;
1945         }
1946     }
1947 
1948     // Partial valid fields are not allowed for SI.
1949     if (IsTileInfoAllZero(pTileInfo))
1950     {
1951         if (IsMacroTiled(tileMode))
1952         {
1953             if (flags.prt)
1954             {
1955                 if (numSamples == 1)
1956                 {
1957                     if (flags.depth)
1958                     {
1959                         switch (bpp)
1960                         {
1961                             case 16:
1962                                 index = 3;
1963                                 break;
1964                             case 32:
1965                                 index = 6;
1966                                 break;
1967                             default:
1968                                 ADDR_ASSERT_ALWAYS();
1969                                 break;
1970                         }
1971                     }
1972                     else
1973                     {
1974                         switch (bpp)
1975                         {
1976                             case 8:
1977                                 index = 21;
1978                                 break;
1979                             case 16:
1980                                 index = 22;
1981                                 break;
1982                             case 32:
1983                                 index = 23;
1984                                 break;
1985                             case 64:
1986                                 index = 24;
1987                                 break;
1988                             case 128:
1989                                 index = 25;
1990                                 break;
1991                             default:
1992                                 break;
1993                         }
1994 
1995                         if (thickness > 1)
1996                         {
1997                             ADDR_ASSERT(bpp != 128);
1998                             index += 5;
1999                         }
2000                     }
2001                 }
2002                 else
2003                 {
2004                     ADDR_ASSERT(numSamples == 4);
2005 
2006                     if (flags.depth)
2007                     {
2008                         switch (bpp)
2009                         {
2010                             case 16:
2011                                 index = 5;
2012                                 break;
2013                             case 32:
2014                                 index = 7;
2015                                 break;
2016                             default:
2017                                 ADDR_ASSERT_ALWAYS();
2018                                 break;
2019                         }
2020                     }
2021                     else
2022                     {
2023                         switch (bpp)
2024                         {
2025                             case 8:
2026                                 index = 23;
2027                                 break;
2028                             case 16:
2029                                 index = 24;
2030                                 break;
2031                             case 32:
2032                                 index = 25;
2033                                 break;
2034                             case 64:
2035                                 index = 30;
2036                                 break;
2037                             default:
2038                                 ADDR_ASSERT_ALWAYS();
2039                                 break;
2040                         }
2041                     }
2042                 }
2043             }//end of PRT part
2044             // See table entries 0-7
2045             else if (flags.depth || flags.stencil)
2046             {
2047                 if (flags.compressZ)
2048                 {
2049                     if (flags.stencil)
2050                     {
2051                         index = 0;
2052                     }
2053                     else
2054                     {
2055                         // optimal tile index for compressed depth/stencil.
2056                         switch (numSamples)
2057                         {
2058                             case 1:
2059                                 index = 0;
2060                                 break;
2061                             case 2:
2062                             case 4:
2063                                 index = 1;
2064                                 break;
2065                             case 8:
2066                                 index = 2;
2067                                 break;
2068                             default:
2069                                 break;
2070                         }
2071                     }
2072                 }
2073                 else // unCompressZ
2074                 {
2075                     index = 3;
2076                 }
2077             }
2078             else //non PRT & non Depth & non Stencil
2079             {
2080                 // See table entries 9-12
2081                 if (inTileType == ADDR_DISPLAYABLE)
2082                 {
2083                     switch (bpp)
2084                     {
2085                         case 8:
2086                             index = 10;
2087                             break;
2088                         case 16:
2089                             index = 11;
2090                             break;
2091                         case 32:
2092                             index = 12;
2093                             break;
2094                         case 64:
2095                             index = 12;
2096                             break;
2097                         default:
2098                             break;
2099                     }
2100                 }
2101                 else
2102                 {
2103                     // See table entries 13-17
2104                     if (thickness == 1)
2105                     {
2106                         if (flags.fmask)
2107                         {
2108                             UINT_32 fmaskPixelSize = bpp * numSamples;
2109 
2110                             switch (fmaskPixelSize)
2111                             {
2112                                 case 8:
2113                                     index = 14;
2114                                     break;
2115                                 case 16:
2116                                     index = 15;
2117                                     break;
2118                                 case 32:
2119                                     index = 16;
2120                                     break;
2121                                 case 64:
2122                                     index = 17;
2123                                     break;
2124                                 default:
2125                                     ADDR_ASSERT_ALWAYS();
2126                             }
2127                         }
2128                         else
2129                         {
2130                             switch (bpp)
2131                             {
2132                                 case 8:
2133                                     index = 14;
2134                                     break;
2135                                 case 16:
2136                                     index = 15;
2137                                     break;
2138                                 case 32:
2139                                     index = 16;
2140                                     break;
2141                                 case 64:
2142                                     index = 17;
2143                                     break;
2144                                 case 128:
2145                                     index = 17;
2146                                     break;
2147                                 default:
2148                                     break;
2149                             }
2150                         }
2151                     }
2152                     else // thick tiling - entries 18-20
2153                     {
2154                         switch (thickness)
2155                         {
2156                             case 4:
2157                                 index = 20;
2158                                 break;
2159                             case 8:
2160                                 index = 19;
2161                                 break;
2162                             default:
2163                                 break;
2164                         }
2165                     }
2166                 }
2167             }
2168         }
2169         else
2170         {
2171             if (tileMode == ADDR_TM_LINEAR_ALIGNED)
2172             {
2173                 index = 8;
2174             }
2175             else if (tileMode == ADDR_TM_LINEAR_GENERAL)
2176             {
2177                 index = TileIndexLinearGeneral;
2178             }
2179             else
2180             {
2181                 if (flags.depth || flags.stencil)
2182                 {
2183                     index = 4;
2184                 }
2185                 else if (inTileType == ADDR_DISPLAYABLE)
2186                 {
2187                     index = 9;
2188                 }
2189                 else if (thickness == 1)
2190                 {
2191                     index = 13;
2192                 }
2193                 else
2194                 {
2195                     index = 18;
2196                 }
2197             }
2198         }
2199 
2200         if (index >= 0 && index <= 31)
2201         {
2202             *pTileInfo      = m_tileTable[index].info;
2203             pOut->tileType  = m_tileTable[index].type;
2204         }
2205 
2206         if (index == TileIndexLinearGeneral)
2207         {
2208             *pTileInfo      = m_tileTable[8].info;
2209             pOut->tileType  = m_tileTable[8].type;
2210         }
2211     }
2212     else
2213     {
2214         if (pTileInfoIn)
2215         {
2216             if (flags.stencil && pTileInfoIn->tileSplitBytes == 0)
2217             {
2218                 // Stencil always uses index 0
2219                 *pTileInfo = m_tileTable[0].info;
2220             }
2221         }
2222         // Pass through tile type
2223         pOut->tileType = inTileType;
2224     }
2225 
2226     pOut->tileIndex = index;
2227     pOut->prtTileIndex = flags.prt;
2228 }
2229 
2230 /**
2231 ****************************************************************************************************
2232 *   SiLib::DecodeGbRegs
2233 *
2234 *   @brief
2235 *       Decodes GB_ADDR_CONFIG and noOfBanks/noOfRanks
2236 *
2237 *   @return
2238 *       TRUE if all settings are valid
2239 *
2240 ****************************************************************************************************
2241 */
DecodeGbRegs(const ADDR_REGISTER_VALUE * pRegValue)2242 BOOL_32 SiLib::DecodeGbRegs(
2243     const ADDR_REGISTER_VALUE* pRegValue) ///< [in] create input
2244 {
2245     GB_ADDR_CONFIG  reg;
2246     BOOL_32         valid = TRUE;
2247 
2248     reg.val = pRegValue->gbAddrConfig;
2249 
2250     switch (reg.f.pipe_interleave_size)
2251     {
2252         case ADDR_CONFIG_PIPE_INTERLEAVE_256B:
2253             m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_256B;
2254             break;
2255         case ADDR_CONFIG_PIPE_INTERLEAVE_512B:
2256             m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_512B;
2257             break;
2258         default:
2259             valid = FALSE;
2260             ADDR_UNHANDLED_CASE();
2261             break;
2262     }
2263 
2264     switch (reg.f.row_size)
2265     {
2266         case ADDR_CONFIG_1KB_ROW:
2267             m_rowSize = ADDR_ROWSIZE_1KB;
2268             break;
2269         case ADDR_CONFIG_2KB_ROW:
2270             m_rowSize = ADDR_ROWSIZE_2KB;
2271             break;
2272         case ADDR_CONFIG_4KB_ROW:
2273             m_rowSize = ADDR_ROWSIZE_4KB;
2274             break;
2275         default:
2276             valid = FALSE;
2277             ADDR_UNHANDLED_CASE();
2278             break;
2279     }
2280 
2281     switch (pRegValue->noOfBanks)
2282     {
2283         case 0:
2284             m_banks = 4;
2285             break;
2286         case 1:
2287             m_banks = 8;
2288             break;
2289         case 2:
2290             m_banks = 16;
2291             break;
2292         default:
2293             valid = FALSE;
2294             ADDR_UNHANDLED_CASE();
2295             break;
2296     }
2297 
2298     switch (pRegValue->noOfRanks)
2299     {
2300         case 0:
2301             m_ranks = 1;
2302             break;
2303         case 1:
2304             m_ranks = 2;
2305             break;
2306         default:
2307             valid = FALSE;
2308             ADDR_UNHANDLED_CASE();
2309             break;
2310     }
2311 
2312     m_logicalBanks = m_banks * m_ranks;
2313 
2314     ADDR_ASSERT(m_logicalBanks <= 16);
2315 
2316     return valid;
2317 }
2318 
2319 /**
2320 ****************************************************************************************************
2321 *   SiLib::HwlInitGlobalParams
2322 *
2323 *   @brief
2324 *       Initializes global parameters
2325 *
2326 *   @return
2327 *       TRUE if all settings are valid
2328 *
2329 ****************************************************************************************************
2330 */
HwlInitGlobalParams(const ADDR_CREATE_INPUT * pCreateIn)2331 BOOL_32 SiLib::HwlInitGlobalParams(
2332     const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input
2333 {
2334     BOOL_32 valid = TRUE;
2335     const ADDR_REGISTER_VALUE* pRegValue = &pCreateIn->regValue;
2336 
2337     valid = DecodeGbRegs(pRegValue);
2338 
2339     if (valid)
2340     {
2341         if (m_settings.isTahiti || m_settings.isPitCairn)
2342         {
2343             m_pipes = 8;
2344         }
2345         else if (m_settings.isCapeVerde || m_settings.isOland)
2346         {
2347             m_pipes = 4;
2348         }
2349         else
2350         {
2351             // Hainan is 2-pipe (m_settings.isHainan == 1)
2352             m_pipes = 2;
2353         }
2354 
2355         valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries);
2356 
2357         if (valid)
2358         {
2359             InitEquationTable();
2360         }
2361 
2362         m_maxSamples = 16;
2363     }
2364 
2365     return valid;
2366 }
2367 
2368 /**
2369 ****************************************************************************************************
2370 *   SiLib::HwlConvertTileInfoToHW
2371 *   @brief
2372 *       Entry of si's ConvertTileInfoToHW
2373 *   @return
2374 *       ADDR_E_RETURNCODE
2375 ****************************************************************************************************
2376 */
HwlConvertTileInfoToHW(const ADDR_CONVERT_TILEINFOTOHW_INPUT * pIn,ADDR_CONVERT_TILEINFOTOHW_OUTPUT * pOut) const2377 ADDR_E_RETURNCODE SiLib::HwlConvertTileInfoToHW(
2378     const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure
2379     ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut      ///< [out] output structure
2380     ) const
2381 {
2382     ADDR_E_RETURNCODE retCode   = ADDR_OK;
2383 
2384     retCode = EgBasedLib::HwlConvertTileInfoToHW(pIn, pOut);
2385 
2386     if (retCode == ADDR_OK)
2387     {
2388         if (pIn->reverse == FALSE)
2389         {
2390             if (pIn->pTileInfo->pipeConfig == ADDR_PIPECFG_INVALID)
2391             {
2392                 retCode = ADDR_INVALIDPARAMS;
2393             }
2394             else
2395             {
2396                 pOut->pTileInfo->pipeConfig =
2397                     static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig - 1);
2398             }
2399         }
2400         else
2401         {
2402             pOut->pTileInfo->pipeConfig =
2403                 static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig + 1);
2404         }
2405     }
2406 
2407     return retCode;
2408 }
2409 
2410 /**
2411 ****************************************************************************************************
2412 *   SiLib::HwlComputeXmaskCoordYFrom8Pipe
2413 *
2414 *   @brief
2415 *       Compute the Y coord which will be added to Xmask Y
2416 *       coord.
2417 *   @return
2418 *       Y coord
2419 ****************************************************************************************************
2420 */
HwlComputeXmaskCoordYFrom8Pipe(UINT_32 pipe,UINT_32 x) const2421 UINT_32 SiLib::HwlComputeXmaskCoordYFrom8Pipe(
2422     UINT_32         pipe,       ///< [in] pipe id
2423     UINT_32         x           ///< [in] tile coord x, which is original x coord / 8
2424     ) const
2425 {
2426     // This function should never be called since it is 6xx/8xx specfic.
2427     // Keep this empty implementation to avoid any mis-use.
2428     ADDR_ASSERT_ALWAYS();
2429 
2430     return 0;
2431 }
2432 
2433 /**
2434 ****************************************************************************************************
2435 *   SiLib::HwlComputeSurfaceCoord2DFromBankPipe
2436 *
2437 *   @brief
2438 *       Compute surface x,y coordinates from bank/pipe info
2439 *   @return
2440 *       N/A
2441 ****************************************************************************************************
2442 */
HwlComputeSurfaceCoord2DFromBankPipe(AddrTileMode tileMode,UINT_32 * pX,UINT_32 * pY,UINT_32 slice,UINT_32 bank,UINT_32 pipe,UINT_32 bankSwizzle,UINT_32 pipeSwizzle,UINT_32 tileSlices,BOOL_32 ignoreSE,ADDR_TILEINFO * pTileInfo) const2443 VOID SiLib::HwlComputeSurfaceCoord2DFromBankPipe(
2444     AddrTileMode        tileMode,   ///< [in] tile mode
2445     UINT_32*            pX,         ///< [in,out] x coordinate
2446     UINT_32*            pY,         ///< [in,out] y coordinate
2447     UINT_32             slice,      ///< [in] slice index
2448     UINT_32             bank,       ///< [in] bank number
2449     UINT_32             pipe,       ///< [in] pipe number
2450     UINT_32             bankSwizzle,///< [in] bank swizzle
2451     UINT_32             pipeSwizzle,///< [in] pipe swizzle
2452     UINT_32             tileSlices, ///< [in] slices in a micro tile
2453     BOOL_32             ignoreSE,   ///< [in] TRUE if shader engines are ignored
2454     ADDR_TILEINFO*      pTileInfo   ///< [in] bank structure. **All fields to be valid on entry**
2455     ) const
2456 {
2457     UINT_32 xBit;
2458     UINT_32 yBit;
2459     UINT_32 yBit3 = 0;
2460     UINT_32 yBit4 = 0;
2461     UINT_32 yBit5 = 0;
2462     UINT_32 yBit6 = 0;
2463 
2464     UINT_32 xBit3 = 0;
2465     UINT_32 xBit4 = 0;
2466     UINT_32 xBit5 = 0;
2467 
2468     UINT_32 numPipes = GetPipePerSurf(pTileInfo->pipeConfig);
2469 
2470     CoordFromBankPipe xyBits = {0};
2471     ComputeSurfaceCoord2DFromBankPipe(tileMode, *pX, *pY, slice, bank, pipe,
2472                                       bankSwizzle, pipeSwizzle, tileSlices, pTileInfo,
2473                                       &xyBits);
2474     yBit3 = xyBits.yBit3;
2475     yBit4 = xyBits.yBit4;
2476     yBit5 = xyBits.yBit5;
2477     yBit6 = xyBits.yBit6;
2478 
2479     xBit3 = xyBits.xBit3;
2480     xBit4 = xyBits.xBit4;
2481     xBit5 = xyBits.xBit5;
2482 
2483     yBit = xyBits.yBits;
2484 
2485     UINT_32 yBitTemp = 0;
2486 
2487     if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) ||
2488         (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32))
2489     {
2490         ADDR_ASSERT(pTileInfo->bankWidth == 1 && pTileInfo->macroAspectRatio > 1);
2491         UINT_32 yBitToCheck = QLog2(pTileInfo->banks) - 1;
2492 
2493         ADDR_ASSERT(yBitToCheck <= 3);
2494 
2495         yBitTemp = _BIT(yBit, yBitToCheck);
2496 
2497         xBit3 = 0;
2498     }
2499 
2500     yBit = Bits2Number(4, yBit6, yBit5, yBit4, yBit3);
2501     xBit = Bits2Number(3, xBit5, xBit4, xBit3);
2502 
2503     *pY += yBit * pTileInfo->bankHeight * MicroTileHeight;
2504     *pX += xBit * numPipes * pTileInfo->bankWidth * MicroTileWidth;
2505 
2506     //calculate the bank and pipe bits in x, y
2507     UINT_32 xTile; //x in micro tile
2508     UINT_32 x3 = 0;
2509     UINT_32 x4 = 0;
2510     UINT_32 x5 = 0;
2511     UINT_32 x6 = 0;
2512     UINT_32 y = *pY;
2513 
2514     UINT_32 pipeBit0 = _BIT(pipe,0);
2515     UINT_32 pipeBit1 = _BIT(pipe,1);
2516     UINT_32 pipeBit2 = _BIT(pipe,2);
2517 
2518     UINT_32 y3 = _BIT(y, 3);
2519     UINT_32 y4 = _BIT(y, 4);
2520     UINT_32 y5 = _BIT(y, 5);
2521     UINT_32 y6 = _BIT(y, 6);
2522 
2523     // bankbit0 after ^x4^x5
2524     UINT_32 bankBit00 = _BIT(bank,0);
2525     UINT_32 bankBit0 = 0;
2526 
2527     switch (pTileInfo->pipeConfig)
2528     {
2529         case ADDR_PIPECFG_P2:
2530             x3 = pipeBit0 ^ y3;
2531             break;
2532         case ADDR_PIPECFG_P4_8x16:
2533             x4 = pipeBit0 ^ y3;
2534             x3 = pipeBit0 ^ y4;
2535             break;
2536         case ADDR_PIPECFG_P4_16x16:
2537             x4 = pipeBit1 ^ y4;
2538             x3 = pipeBit0 ^ y3 ^ x4;
2539             break;
2540         case ADDR_PIPECFG_P4_16x32:
2541             x4 = pipeBit1 ^ y4;
2542             x3 = pipeBit0 ^ y3 ^ x4;
2543             break;
2544         case ADDR_PIPECFG_P4_32x32:
2545             x5 = pipeBit1 ^ y5;
2546             x3 = pipeBit0 ^ y3 ^ x5;
2547             bankBit0 = yBitTemp ^ x5;
2548             x4 = bankBit00 ^ x5 ^ bankBit0;
2549             *pX += x5 * 4 * 1 * 8; // x5 * num_pipes * bank_width * 8;
2550             break;
2551         case ADDR_PIPECFG_P8_16x16_8x16:
2552             x3 = pipeBit1 ^ y5;
2553             x4 = pipeBit2 ^ y4;
2554             x5 = pipeBit0 ^ y3 ^ x4;
2555             break;
2556         case ADDR_PIPECFG_P8_16x32_8x16:
2557             x3 = pipeBit1 ^ y4;
2558             x4 = pipeBit2 ^ y5;
2559             x5 = pipeBit0 ^ y3 ^ x4;
2560             break;
2561         case ADDR_PIPECFG_P8_32x32_8x16:
2562             x3 = pipeBit1 ^ y4;
2563             x5 = pipeBit2 ^ y5;
2564             x4 = pipeBit0 ^ y3 ^ x5;
2565             break;
2566         case ADDR_PIPECFG_P8_16x32_16x16:
2567             x4 = pipeBit2 ^ y5;
2568             x5 = pipeBit1 ^ y4;
2569             x3 = pipeBit0 ^ y3 ^ x4;
2570             break;
2571         case ADDR_PIPECFG_P8_32x32_16x16:
2572             x5 = pipeBit2 ^ y5;
2573             x4 = pipeBit1 ^ y4;
2574             x3 = pipeBit0 ^ y3 ^ x4;
2575             break;
2576         case ADDR_PIPECFG_P8_32x32_16x32:
2577             x5 = pipeBit2 ^ y5;
2578             x4 = pipeBit1 ^ y6;
2579             x3 = pipeBit0 ^ y3 ^ x4;
2580             break;
2581         case ADDR_PIPECFG_P8_32x64_32x32:
2582             x6 = pipeBit1 ^ y5;
2583             x5 = pipeBit2 ^ y6;
2584             x3 = pipeBit0 ^ y3 ^ x5;
2585             bankBit0 = yBitTemp ^ x6;
2586             x4 = bankBit00 ^ x5 ^ bankBit0;
2587             *pX += x6 * 8 * 1 * 8; // x6 * num_pipes * bank_width * 8;
2588             break;
2589         default:
2590             ADDR_ASSERT_ALWAYS();
2591     }
2592 
2593     xTile = Bits2Number(3, x5, x4, x3);
2594 
2595     *pX += xTile << 3;
2596 }
2597 
2598 /**
2599 ****************************************************************************************************
2600 *   SiLib::HwlPreAdjustBank
2601 *
2602 *   @brief
2603 *       Adjust bank before calculating address acoording to bank/pipe
2604 *   @return
2605 *       Adjusted bank
2606 ****************************************************************************************************
2607 */
HwlPreAdjustBank(UINT_32 tileX,UINT_32 bank,ADDR_TILEINFO * pTileInfo) const2608 UINT_32 SiLib::HwlPreAdjustBank(
2609     UINT_32         tileX,      ///< [in] x coordinate in unit of tile
2610     UINT_32         bank,       ///< [in] bank
2611     ADDR_TILEINFO*  pTileInfo   ///< [in] tile info
2612     ) const
2613 {
2614     if (((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) ||
2615         (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)) && (pTileInfo->bankWidth == 1))
2616     {
2617         UINT_32 bankBit0 = _BIT(bank, 0);
2618         UINT_32 x4 = _BIT(tileX, 1);
2619         UINT_32 x5 = _BIT(tileX, 2);
2620 
2621         bankBit0 = bankBit0 ^ x4 ^ x5;
2622         bank |= bankBit0;
2623 
2624         ADDR_ASSERT(pTileInfo->macroAspectRatio > 1);
2625     }
2626 
2627     return bank;
2628 }
2629 
2630 /**
2631 ****************************************************************************************************
2632 *   SiLib::HwlComputeSurfaceInfo
2633 *
2634 *   @brief
2635 *       Entry of si's ComputeSurfaceInfo
2636 *   @return
2637 *       ADDR_E_RETURNCODE
2638 ****************************************************************************************************
2639 */
HwlComputeSurfaceInfo(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2640 ADDR_E_RETURNCODE SiLib::HwlComputeSurfaceInfo(
2641     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,    ///< [in] input structure
2642     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pOut    ///< [out] output structure
2643     ) const
2644 {
2645     pOut->tileIndex = pIn->tileIndex;
2646 
2647     ADDR_E_RETURNCODE retCode = EgBasedLib::HwlComputeSurfaceInfo(pIn, pOut);
2648 
2649     UINT_32 tileIndex = static_cast<UINT_32>(pOut->tileIndex);
2650 
2651     if (((pIn->flags.needEquation   == TRUE) ||
2652          (pIn->flags.preferEquation == TRUE)) &&
2653         (pIn->numSamples <= 1) &&
2654         (tileIndex < TileTableSize))
2655     {
2656         static const UINT_32 SiUncompressDepthTileIndex = 3;
2657 
2658         if ((pIn->numSlices > 1) &&
2659             (IsMacroTiled(pOut->tileMode) == TRUE) &&
2660             ((m_chipFamily == ADDR_CHIP_FAMILY_SI) ||
2661              (IsPrtTileMode(pOut->tileMode) == FALSE)))
2662         {
2663             pOut->equationIndex = ADDR_INVALID_EQUATION_INDEX;
2664         }
2665         else if ((pIn->flags.prt == FALSE) &&
2666                  (m_uncompressDepthEqIndex != 0) &&
2667                  (tileIndex == SiUncompressDepthTileIndex))
2668         {
2669             pOut->equationIndex = m_uncompressDepthEqIndex + Log2(pIn->bpp >> 3);
2670         }
2671         else
2672         {
2673 
2674             pOut->equationIndex = m_equationLookupTable[Log2(pIn->bpp >> 3)][tileIndex];
2675         }
2676 
2677         if (pOut->equationIndex != ADDR_INVALID_EQUATION_INDEX)
2678         {
2679             pOut->blockWidth = m_blockWidth[pOut->equationIndex];
2680 
2681             pOut->blockHeight = m_blockHeight[pOut->equationIndex];
2682 
2683             pOut->blockSlices = m_blockSlices[pOut->equationIndex];
2684         }
2685     }
2686     else
2687     {
2688         pOut->equationIndex = ADDR_INVALID_EQUATION_INDEX;
2689     }
2690 
2691     return retCode;
2692 }
2693 
2694 /**
2695 ****************************************************************************************************
2696 *   SiLib::HwlComputeMipLevel
2697 *   @brief
2698 *       Compute MipLevel info (including level 0)
2699 *   @return
2700 *       TRUE if HWL's handled
2701 ****************************************************************************************************
2702 */
HwlComputeMipLevel(ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn) const2703 BOOL_32 SiLib::HwlComputeMipLevel(
2704     ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in,out] Input structure
2705     ) const
2706 {
2707     // basePitch is calculated from level 0 so we only check this for mipLevel > 0
2708     if (pIn->mipLevel > 0)
2709     {
2710         // Note: Don't check expand 3x formats(96 bit) as the basePitch is not pow2 even if
2711         // we explicity set pow2Pad flag. The 3x base pitch is padded to pow2 but after being
2712         // divided by expandX factor (3) - to program texture pitch, the basePitch is never pow2.
2713         if (ElemLib::IsExpand3x(pIn->format) == FALSE)
2714         {
2715             // Sublevel pitches are generated from base level pitch instead of width on SI
2716             // If pow2Pad is 0, we don't assert - as this is not really used for a mip chain
2717             ADDR_ASSERT((pIn->flags.pow2Pad == FALSE) ||
2718                         ((pIn->basePitch != 0) && IsPow2(pIn->basePitch)));
2719         }
2720 
2721         if (pIn->basePitch != 0)
2722         {
2723             pIn->width = Max(1u, pIn->basePitch >> pIn->mipLevel);
2724         }
2725     }
2726 
2727     // pow2Pad is done in PostComputeMipLevel
2728 
2729     return TRUE;
2730 }
2731 
2732 /**
2733 ****************************************************************************************************
2734 *   SiLib::HwlCheckLastMacroTiledLvl
2735 *
2736 *   @brief
2737 *       Sets pOut->last2DLevel to TRUE if it is
2738 *   @note
2739 *
2740 ****************************************************************************************************
2741 */
HwlCheckLastMacroTiledLvl(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2742 VOID SiLib::HwlCheckLastMacroTiledLvl(
2743     const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure
2744     ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut      ///< [in,out] Output structure (used as input, too)
2745     ) const
2746 {
2747     // pow2Pad covers all mipmap cases
2748     if (pIn->flags.pow2Pad)
2749     {
2750         ADDR_ASSERT(IsMacroTiled(pIn->tileMode));
2751 
2752         UINT_32 nextPitch;
2753         UINT_32 nextHeight;
2754         UINT_32 nextSlices;
2755 
2756         AddrTileMode nextTileMode;
2757 
2758         if (pIn->mipLevel == 0 || pIn->basePitch == 0)
2759         {
2760             // Base level or fail-safe case (basePitch == 0)
2761             nextPitch = pOut->pitch >> 1;
2762         }
2763         else
2764         {
2765             // Sub levels
2766             nextPitch = pIn->basePitch >> (pIn->mipLevel + 1);
2767         }
2768 
2769         // nextHeight must be shifted from this level's original height rather than a pow2 padded
2770         // one but this requires original height stored somewhere (pOut->height)
2771         ADDR_ASSERT(pOut->height != 0);
2772 
2773         // next level's height is just current level's >> 1 in pixels
2774         nextHeight = pOut->height >> 1;
2775         // Special format such as FMT_1 and FMT_32_32_32 can be linear only so we consider block
2776         // compressed foramts
2777         if (ElemLib::IsBlockCompressed(pIn->format))
2778         {
2779             nextHeight = (nextHeight + 3) / 4;
2780         }
2781         nextHeight = NextPow2(nextHeight);
2782 
2783         // nextSlices may be 0 if this level's is 1
2784         if (pIn->flags.volume)
2785         {
2786             nextSlices = Max(1u, pIn->numSlices >> 1);
2787         }
2788         else
2789         {
2790             nextSlices = pIn->numSlices;
2791         }
2792 
2793         nextTileMode = ComputeSurfaceMipLevelTileMode(pIn->tileMode,
2794                                                       pIn->bpp,
2795                                                       nextPitch,
2796                                                       nextHeight,
2797                                                       nextSlices,
2798                                                       pIn->numSamples,
2799                                                       pOut->blockWidth,
2800                                                       pOut->blockHeight,
2801                                                       pOut->pTileInfo);
2802 
2803         pOut->last2DLevel = IsMicroTiled(nextTileMode);
2804     }
2805 }
2806 
2807 /**
2808 ****************************************************************************************************
2809 *   SiLib::HwlDegradeThickTileMode
2810 *
2811 *   @brief
2812 *       Degrades valid tile mode for thick modes if needed
2813 *
2814 *   @return
2815 *       Suitable tile mode
2816 ****************************************************************************************************
2817 */
HwlDegradeThickTileMode(AddrTileMode baseTileMode,UINT_32 numSlices,UINT_32 * pBytesPerTile) const2818 AddrTileMode SiLib::HwlDegradeThickTileMode(
2819     AddrTileMode        baseTileMode,   ///< base tile mode
2820     UINT_32             numSlices,      ///< current number of slices
2821     UINT_32*            pBytesPerTile   ///< [in,out] pointer to bytes per slice
2822     ) const
2823 {
2824     return EgBasedLib::HwlDegradeThickTileMode(baseTileMode, numSlices, pBytesPerTile);
2825 }
2826 
2827 /**
2828 ****************************************************************************************************
2829 *   SiLib::HwlTileInfoEqual
2830 *
2831 *   @brief
2832 *       Return TRUE if all field are equal
2833 *   @note
2834 *       Only takes care of current HWL's data
2835 ****************************************************************************************************
2836 */
HwlTileInfoEqual(const ADDR_TILEINFO * pLeft,const ADDR_TILEINFO * pRight) const2837 BOOL_32 SiLib::HwlTileInfoEqual(
2838     const ADDR_TILEINFO* pLeft, ///<[in] Left compare operand
2839     const ADDR_TILEINFO* pRight ///<[in] Right compare operand
2840     ) const
2841 {
2842     BOOL_32 equal = FALSE;
2843 
2844     if (pLeft->pipeConfig == pRight->pipeConfig)
2845     {
2846         equal =  EgBasedLib::HwlTileInfoEqual(pLeft, pRight);
2847     }
2848 
2849     return equal;
2850 }
2851 
2852 /**
2853 ****************************************************************************************************
2854 *   SiLib::GetTileSettings
2855 *
2856 *   @brief
2857 *       Get tile setting infos by index.
2858 *   @return
2859 *       Tile setting info.
2860 ****************************************************************************************************
2861 */
GetTileSetting(UINT_32 index) const2862 const TileConfig* SiLib::GetTileSetting(
2863     UINT_32 index          ///< [in] Tile index
2864     ) const
2865 {
2866     ADDR_ASSERT(index < m_noOfEntries);
2867     return &m_tileTable[index];
2868 }
2869 
2870 /**
2871 ****************************************************************************************************
2872 *   SiLib::HwlPostCheckTileIndex
2873 *
2874 *   @brief
2875 *       Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches
2876 *       tile mode/type/info and change the index if needed
2877 *   @return
2878 *       Tile index.
2879 ****************************************************************************************************
2880 */
HwlPostCheckTileIndex(const ADDR_TILEINFO * pInfo,AddrTileMode mode,AddrTileType type,INT curIndex) const2881 INT_32 SiLib::HwlPostCheckTileIndex(
2882     const ADDR_TILEINFO* pInfo,     ///< [in] Tile Info
2883     AddrTileMode         mode,      ///< [in] Tile mode
2884     AddrTileType         type,      ///< [in] Tile type
2885     INT                  curIndex   ///< [in] Current index assigned in HwlSetupTileInfo
2886     ) const
2887 {
2888     INT_32 index = curIndex;
2889 
2890     if (mode == ADDR_TM_LINEAR_GENERAL)
2891     {
2892         index = TileIndexLinearGeneral;
2893     }
2894     else
2895     {
2896         BOOL_32 macroTiled = IsMacroTiled(mode);
2897 
2898         // We need to find a new index if either of them is true
2899         // 1. curIndex is invalid
2900         // 2. tile mode is changed
2901         // 3. tile info does not match for macro tiled
2902         if ((index == TileIndexInvalid         ||
2903             (mode != m_tileTable[index].mode)  ||
2904             (macroTiled && (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) == FALSE))))
2905         {
2906             for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++)
2907             {
2908                 if (macroTiled)
2909                 {
2910                     // macro tile modes need all to match
2911                     if (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) &&
2912                         (mode == m_tileTable[index].mode)                 &&
2913                         (type == m_tileTable[index].type))
2914                     {
2915                         break;
2916                     }
2917                 }
2918                 else if (mode == ADDR_TM_LINEAR_ALIGNED)
2919                 {
2920                     // linear mode only needs tile mode to match
2921                     if (mode == m_tileTable[index].mode)
2922                     {
2923                         break;
2924                     }
2925                 }
2926                 else
2927                 {
2928                     // micro tile modes only need tile mode and tile type to match
2929                     if (mode == m_tileTable[index].mode &&
2930                         type == m_tileTable[index].type)
2931                     {
2932                         break;
2933                     }
2934                 }
2935             }
2936         }
2937     }
2938 
2939     ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries));
2940 
2941     if (index >= static_cast<INT_32>(m_noOfEntries))
2942     {
2943         index = TileIndexInvalid;
2944     }
2945 
2946     return index;
2947 }
2948 
2949 /**
2950 ****************************************************************************************************
2951 *   SiLib::HwlSetupTileCfg
2952 *
2953 *   @brief
2954 *       Map tile index to tile setting.
2955 *   @return
2956 *       ADDR_E_RETURNCODE
2957 ****************************************************************************************************
2958 */
HwlSetupTileCfg(UINT_32 bpp,INT_32 index,INT_32 macroModeIndex,ADDR_TILEINFO * pInfo,AddrTileMode * pMode,AddrTileType * pType) const2959 ADDR_E_RETURNCODE SiLib::HwlSetupTileCfg(
2960     UINT_32         bpp,            ///< Bits per pixel
2961     INT_32          index,          ///< Tile index
2962     INT_32          macroModeIndex, ///< Index in macro tile mode table(CI)
2963     ADDR_TILEINFO*  pInfo,          ///< [out] Tile Info
2964     AddrTileMode*   pMode,          ///< [out] Tile mode
2965     AddrTileType*   pType           ///< [out] Tile type
2966     ) const
2967 {
2968     ADDR_E_RETURNCODE returnCode = ADDR_OK;
2969 
2970     // Global flag to control usage of tileIndex
2971     if (UseTileIndex(index))
2972     {
2973         if (index == TileIndexLinearGeneral)
2974         {
2975             if (pMode)
2976             {
2977                 *pMode = ADDR_TM_LINEAR_GENERAL;
2978             }
2979 
2980             if (pType)
2981             {
2982                 *pType = ADDR_DISPLAYABLE;
2983             }
2984 
2985             if (pInfo)
2986             {
2987                 pInfo->banks = 2;
2988                 pInfo->bankWidth = 1;
2989                 pInfo->bankHeight = 1;
2990                 pInfo->macroAspectRatio = 1;
2991                 pInfo->tileSplitBytes = 64;
2992                 pInfo->pipeConfig = ADDR_PIPECFG_P2;
2993             }
2994         }
2995         else if (static_cast<UINT_32>(index) >= m_noOfEntries)
2996         {
2997             returnCode = ADDR_INVALIDPARAMS;
2998         }
2999         else
3000         {
3001             const TileConfig* pCfgTable = GetTileSetting(index);
3002 
3003             if (pInfo)
3004             {
3005                 *pInfo = pCfgTable->info;
3006             }
3007             else
3008             {
3009                 if (IsMacroTiled(pCfgTable->mode))
3010                 {
3011                     returnCode = ADDR_INVALIDPARAMS;
3012                 }
3013             }
3014 
3015             if (pMode)
3016             {
3017                 *pMode = pCfgTable->mode;
3018             }
3019 
3020             if (pType)
3021             {
3022                 *pType = pCfgTable->type;
3023             }
3024         }
3025     }
3026 
3027     return returnCode;
3028 }
3029 
3030 /**
3031 ****************************************************************************************************
3032 *   SiLib::ReadGbTileMode
3033 *
3034 *   @brief
3035 *       Convert GB_TILE_MODE HW value to TileConfig.
3036 *   @return
3037 *       NA.
3038 ****************************************************************************************************
3039 */
ReadGbTileMode(UINT_32 regValue,TileConfig * pCfg) const3040 VOID SiLib::ReadGbTileMode(
3041     UINT_32     regValue,   ///< [in] GB_TILE_MODE register
3042     TileConfig* pCfg        ///< [out] output structure
3043     ) const
3044 {
3045     GB_TILE_MODE gbTileMode;
3046     gbTileMode.val = regValue;
3047 
3048     pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode);
3049     pCfg->info.bankHeight = 1 << gbTileMode.f.bank_height;
3050     pCfg->info.bankWidth = 1 << gbTileMode.f.bank_width;
3051     pCfg->info.banks = 1 << (gbTileMode.f.num_banks + 1);
3052     pCfg->info.macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect;
3053     pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split;
3054     pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1);
3055 
3056     UINT_32 regArrayMode = gbTileMode.f.array_mode;
3057 
3058     pCfg->mode = static_cast<AddrTileMode>(regArrayMode);
3059 
3060     if (regArrayMode == 8) //ARRAY_2D_TILED_XTHICK
3061     {
3062         pCfg->mode = ADDR_TM_2D_TILED_XTHICK;
3063     }
3064     else if (regArrayMode >= 14) //ARRAY_3D_TILED_XTHICK
3065     {
3066         pCfg->mode = static_cast<AddrTileMode>(pCfg->mode + 3);
3067     }
3068 }
3069 
3070 /**
3071 ****************************************************************************************************
3072 *   SiLib::InitTileSettingTable
3073 *
3074 *   @brief
3075 *       Initialize the ADDR_TILE_CONFIG table.
3076 *   @return
3077 *       TRUE if tile table is correctly initialized
3078 ****************************************************************************************************
3079 */
InitTileSettingTable(const UINT_32 * pCfg,UINT_32 noOfEntries)3080 BOOL_32 SiLib::InitTileSettingTable(
3081     const UINT_32*  pCfg,           ///< [in] Pointer to table of tile configs
3082     UINT_32         noOfEntries     ///< [in] Numbe of entries in the table above
3083     )
3084 {
3085     BOOL_32 initOk = TRUE;
3086 
3087     ADDR_ASSERT(noOfEntries <= TileTableSize);
3088 
3089     memset(m_tileTable, 0, sizeof(m_tileTable));
3090 
3091     if (noOfEntries != 0)
3092     {
3093         m_noOfEntries = noOfEntries;
3094     }
3095     else
3096     {
3097         m_noOfEntries = TileTableSize;
3098     }
3099 
3100     if (pCfg) // From Client
3101     {
3102         for (UINT_32 i = 0; i < m_noOfEntries; i++)
3103         {
3104             ReadGbTileMode(*(pCfg + i), &m_tileTable[i]);
3105         }
3106     }
3107     else
3108     {
3109         ADDR_ASSERT_ALWAYS();
3110         initOk = FALSE;
3111     }
3112 
3113     if (initOk)
3114     {
3115         ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED);
3116     }
3117 
3118     return initOk;
3119 }
3120 
3121 /**
3122 ****************************************************************************************************
3123 *   SiLib::HwlGetTileIndex
3124 *
3125 *   @brief
3126 *       Return the virtual/real index for given mode/type/info
3127 *   @return
3128 *       ADDR_OK if successful.
3129 ****************************************************************************************************
3130 */
HwlGetTileIndex(const ADDR_GET_TILEINDEX_INPUT * pIn,ADDR_GET_TILEINDEX_OUTPUT * pOut) const3131 ADDR_E_RETURNCODE SiLib::HwlGetTileIndex(
3132     const ADDR_GET_TILEINDEX_INPUT* pIn,
3133     ADDR_GET_TILEINDEX_OUTPUT*      pOut) const
3134 {
3135     ADDR_E_RETURNCODE returnCode = ADDR_OK;
3136 
3137     pOut->index = HwlPostCheckTileIndex(pIn->pTileInfo, pIn->tileMode, pIn->tileType);
3138 
3139     return returnCode;
3140 }
3141 
3142 /**
3143 ****************************************************************************************************
3144 *   SiLib::HwlFmaskPreThunkSurfInfo
3145 *
3146 *   @brief
3147 *       Some preparation before thunking a ComputeSurfaceInfo call for Fmask
3148 *   @return
3149 *       ADDR_E_RETURNCODE
3150 ****************************************************************************************************
3151 */
HwlFmaskPreThunkSurfInfo(const ADDR_COMPUTE_FMASK_INFO_INPUT * pFmaskIn,const ADDR_COMPUTE_FMASK_INFO_OUTPUT * pFmaskOut,ADDR_COMPUTE_SURFACE_INFO_INPUT * pSurfIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pSurfOut) const3152 VOID SiLib::HwlFmaskPreThunkSurfInfo(
3153     const ADDR_COMPUTE_FMASK_INFO_INPUT*    pFmaskIn,   ///< [in] Input of fmask info
3154     const ADDR_COMPUTE_FMASK_INFO_OUTPUT*   pFmaskOut,  ///< [in] Output of fmask info
3155     ADDR_COMPUTE_SURFACE_INFO_INPUT*        pSurfIn,    ///< [out] Input of thunked surface info
3156     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pSurfOut    ///< [out] Output of thunked surface info
3157     ) const
3158 {
3159     pSurfIn->tileIndex = pFmaskIn->tileIndex;
3160 }
3161 
3162 /**
3163 ****************************************************************************************************
3164 *   SiLib::HwlFmaskPostThunkSurfInfo
3165 *
3166 *   @brief
3167 *       Copy hwl extra field after calling thunked ComputeSurfaceInfo
3168 *   @return
3169 *       ADDR_E_RETURNCODE
3170 ****************************************************************************************************
3171 */
HwlFmaskPostThunkSurfInfo(const ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pSurfOut,ADDR_COMPUTE_FMASK_INFO_OUTPUT * pFmaskOut) const3172 VOID SiLib::HwlFmaskPostThunkSurfInfo(
3173     const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut,   ///< [in] Output of surface info
3174     ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut           ///< [out] Output of fmask info
3175     ) const
3176 {
3177     pFmaskOut->macroModeIndex = TileIndexInvalid;
3178     pFmaskOut->tileIndex = pSurfOut->tileIndex;
3179 }
3180 
3181 /**
3182 ****************************************************************************************************
3183 *   SiLib::HwlComputeFmaskBits
3184 *   @brief
3185 *       Computes fmask bits
3186 *   @return
3187 *       Fmask bits
3188 ****************************************************************************************************
3189 */
HwlComputeFmaskBits(const ADDR_COMPUTE_FMASK_INFO_INPUT * pIn,UINT_32 * pNumSamples) const3190 UINT_32 SiLib::HwlComputeFmaskBits(
3191     const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn,
3192     UINT_32* pNumSamples
3193     ) const
3194 {
3195     UINT_32 numSamples = pIn->numSamples;
3196     UINT_32 numFrags = GetNumFragments(numSamples, pIn->numFrags);
3197     UINT_32 bpp;
3198 
3199     if (numFrags != numSamples) // EQAA
3200     {
3201         ADDR_ASSERT(numFrags <= 8);
3202 
3203         if (pIn->resolved == FALSE)
3204         {
3205             if (numFrags == 1)
3206             {
3207                 bpp          = 1;
3208                 numSamples   = numSamples == 16 ? 16 : 8;
3209             }
3210             else if (numFrags == 2)
3211             {
3212                 ADDR_ASSERT(numSamples >= 4);
3213 
3214                 bpp          = 2;
3215                 numSamples   = numSamples;
3216             }
3217             else if (numFrags == 4)
3218             {
3219                 ADDR_ASSERT(numSamples >= 4);
3220 
3221                 bpp          = 4;
3222                 numSamples   = numSamples;
3223             }
3224             else // numFrags == 8
3225             {
3226                 ADDR_ASSERT(numSamples == 16);
3227 
3228                 bpp          = 4;
3229                 numSamples   = numSamples;
3230             }
3231         }
3232         else
3233         {
3234             if (numFrags == 1)
3235             {
3236                 bpp          = (numSamples == 16) ? 16 : 8;
3237                 numSamples   = 1;
3238             }
3239             else if (numFrags == 2)
3240             {
3241                 ADDR_ASSERT(numSamples >= 4);
3242 
3243                 bpp          = numSamples*2;
3244                 numSamples   = 1;
3245             }
3246             else if (numFrags == 4)
3247             {
3248                 ADDR_ASSERT(numSamples >= 4);
3249 
3250                 bpp          = numSamples*4;
3251                 numSamples   = 1;
3252             }
3253             else // numFrags == 8
3254             {
3255                 ADDR_ASSERT(numSamples >= 16);
3256 
3257                 bpp          = 16*4;
3258                 numSamples   = 1;
3259             }
3260         }
3261     }
3262     else // Normal AA
3263     {
3264         if (pIn->resolved == FALSE)
3265         {
3266             bpp          = ComputeFmaskNumPlanesFromNumSamples(numSamples);
3267             numSamples   = numSamples == 2 ? 8 : numSamples;
3268         }
3269         else
3270         {
3271             // The same as 8XX
3272             bpp          = ComputeFmaskResolvedBppFromNumSamples(numSamples);
3273             numSamples   = 1; // 1x sample
3274         }
3275     }
3276 
3277     SafeAssign(pNumSamples, numSamples);
3278 
3279     return bpp;
3280 }
3281 
3282 /**
3283 ****************************************************************************************************
3284 *   SiLib::HwlOptimizeTileMode
3285 *
3286 *   @brief
3287 *       Optimize tile mode on SI
3288 *
3289 *   @return
3290 *       N/A
3291 *
3292 ****************************************************************************************************
3293 */
HwlOptimizeTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const3294 VOID SiLib::HwlOptimizeTileMode(
3295     ADDR_COMPUTE_SURFACE_INFO_INPUT*    pInOut      ///< [in,out] input output structure
3296     ) const
3297 {
3298     AddrTileMode tileMode = pInOut->tileMode;
3299 
3300     if ((pInOut->flags.needEquation == TRUE) &&
3301         (IsMacroTiled(tileMode) == TRUE) &&
3302         (pInOut->numSamples <= 1))
3303     {
3304         UINT_32 thickness = Thickness(tileMode);
3305 
3306         if (thickness > 1)
3307         {
3308             tileMode = ADDR_TM_1D_TILED_THICK;
3309         }
3310         else if (pInOut->numSlices > 1)
3311         {
3312             tileMode = ADDR_TM_1D_TILED_THIN1;
3313         }
3314         else
3315         {
3316             tileMode = ADDR_TM_2D_TILED_THIN1;
3317         }
3318     }
3319 
3320     if (tileMode != pInOut->tileMode)
3321     {
3322         pInOut->tileMode = tileMode;
3323     }
3324 }
3325 
3326 /**
3327 ****************************************************************************************************
3328 *   SiLib::HwlOverrideTileMode
3329 *
3330 *   @brief
3331 *       Override tile modes (for PRT only, avoid client passes in an invalid PRT mode for SI.
3332 *
3333 *   @return
3334 *       N/A
3335 *
3336 ****************************************************************************************************
3337 */
HwlOverrideTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const3338 VOID SiLib::HwlOverrideTileMode(
3339     ADDR_COMPUTE_SURFACE_INFO_INPUT*    pInOut          ///< [in,out] input output structure
3340     ) const
3341 {
3342     AddrTileMode tileMode = pInOut->tileMode;
3343 
3344     switch (tileMode)
3345     {
3346         case ADDR_TM_PRT_TILED_THIN1:
3347             tileMode = ADDR_TM_2D_TILED_THIN1;
3348             break;
3349 
3350         case ADDR_TM_PRT_TILED_THICK:
3351             tileMode = ADDR_TM_2D_TILED_THICK;
3352             break;
3353 
3354         case ADDR_TM_PRT_2D_TILED_THICK:
3355             tileMode = ADDR_TM_2D_TILED_THICK;
3356             break;
3357 
3358         case ADDR_TM_PRT_3D_TILED_THICK:
3359             tileMode = ADDR_TM_3D_TILED_THICK;
3360             break;
3361 
3362         default:
3363             break;
3364     }
3365 
3366     if (tileMode != pInOut->tileMode)
3367     {
3368         pInOut->tileMode  = tileMode;
3369         // Only PRT tile modes are overridden for now. Revisit this once new modes are added above.
3370         pInOut->flags.prt = TRUE;
3371     }
3372 }
3373 
3374 /**
3375 ****************************************************************************************************
3376 *   SiLib::HwlSetPrtTileMode
3377 *
3378 *   @brief
3379 *       Set prt tile modes.
3380 *
3381 *   @return
3382 *       N/A
3383 *
3384 ****************************************************************************************************
3385 */
HwlSetPrtTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const3386 VOID SiLib::HwlSetPrtTileMode(
3387     ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut     ///< [in,out] input output structure
3388     ) const
3389 {
3390     pInOut->tileMode = ADDR_TM_2D_TILED_THIN1;
3391     pInOut->tileType = (pInOut->tileType == ADDR_DEPTH_SAMPLE_ORDER) ?
3392                        ADDR_DEPTH_SAMPLE_ORDER : ADDR_NON_DISPLAYABLE;
3393     pInOut->flags.prt = TRUE;
3394 }
3395 
3396 /**
3397 ****************************************************************************************************
3398 *   SiLib::HwlSelectTileMode
3399 *
3400 *   @brief
3401 *       Select tile modes.
3402 *
3403 *   @return
3404 *       N/A
3405 *
3406 ****************************************************************************************************
3407 */
HwlSelectTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const3408 VOID SiLib::HwlSelectTileMode(
3409     ADDR_COMPUTE_SURFACE_INFO_INPUT* pInOut     ///< [in,out] input output structure
3410     ) const
3411 {
3412     AddrTileMode tileMode;
3413     AddrTileType tileType;
3414 
3415     if (pInOut->flags.volume)
3416     {
3417         if (pInOut->numSlices >= 8)
3418         {
3419             tileMode = ADDR_TM_2D_TILED_XTHICK;
3420         }
3421         else if (pInOut->numSlices >= 4)
3422         {
3423             tileMode = ADDR_TM_2D_TILED_THICK;
3424         }
3425         else
3426         {
3427             tileMode = ADDR_TM_2D_TILED_THIN1;
3428         }
3429         tileType = ADDR_NON_DISPLAYABLE;
3430     }
3431     else
3432     {
3433         tileMode = ADDR_TM_2D_TILED_THIN1;
3434 
3435         if (pInOut->flags.depth || pInOut->flags.stencil)
3436         {
3437             tileType = ADDR_DEPTH_SAMPLE_ORDER;
3438         }
3439         else if ((pInOut->bpp <= 32) ||
3440                  (pInOut->flags.display == TRUE) ||
3441                  (pInOut->flags.overlay == TRUE))
3442         {
3443             tileType = ADDR_DISPLAYABLE;
3444         }
3445         else
3446         {
3447             tileType = ADDR_NON_DISPLAYABLE;
3448         }
3449     }
3450 
3451     if (pInOut->flags.prt)
3452     {
3453         tileMode = ADDR_TM_2D_TILED_THIN1;
3454         tileType = (tileType == ADDR_DISPLAYABLE) ? ADDR_NON_DISPLAYABLE : tileType;
3455     }
3456 
3457     pInOut->tileMode = tileMode;
3458     pInOut->tileType = tileType;
3459 
3460     // Optimize tile mode if possible
3461     pInOut->flags.opt4Space = TRUE;
3462 
3463     // Optimize tile mode if possible
3464     OptimizeTileMode(pInOut);
3465 
3466     HwlOverrideTileMode(pInOut);
3467 }
3468 
3469 /**
3470 ****************************************************************************************************
3471 *   SiLib::HwlGetMaxAlignments
3472 *
3473 *   @brief
3474 *       Gets maximum alignments
3475 *   @return
3476 *       ADDR_E_RETURNCODE
3477 ****************************************************************************************************
3478 */
HwlGetMaxAlignments(ADDR_GET_MAX_ALIGNMENTS_OUTPUT * pOut) const3479 ADDR_E_RETURNCODE SiLib::HwlGetMaxAlignments(
3480     ADDR_GET_MAX_ALIGNMENTS_OUTPUT* pOut    ///< [out] output structure
3481     ) const
3482 {
3483     const UINT_32 pipes = HwlGetPipes(&m_tileTable[0].info);
3484 
3485     // Initial size is 64 KiB for PRT.
3486     UINT_64 maxBaseAlign = 64 * 1024;
3487 
3488     for (UINT_32 i = 0; i < m_noOfEntries; i++)
3489     {
3490         if ((IsMacroTiled(m_tileTable[i].mode) == TRUE) &&
3491             (IsPrtTileMode(m_tileTable[i].mode) == FALSE))
3492         {
3493             // The maximum tile size is 16 byte-per-pixel and either 8-sample or 8-slice.
3494             UINT_32 tileSize = Min(m_tileTable[i].info.tileSplitBytes,
3495                                    MicroTilePixels * 8 * 16);
3496 
3497             UINT_64 baseAlign = tileSize * pipes * m_tileTable[i].info.banks *
3498                                 m_tileTable[i].info.bankWidth * m_tileTable[i].info.bankHeight;
3499 
3500             if (baseAlign > maxBaseAlign)
3501             {
3502                 maxBaseAlign = baseAlign;
3503             }
3504         }
3505     }
3506 
3507     if (pOut != NULL)
3508     {
3509         pOut->baseAlign = maxBaseAlign;
3510     }
3511 
3512     return ADDR_OK;
3513 }
3514 
3515 /**
3516 ****************************************************************************************************
3517 *   SiLib::HwlComputeSurfaceAlignmentsMacroTiled
3518 *
3519 *   @brief
3520 *       Hardware layer function to compute alignment request for macro tile mode
3521 *
3522 *   @return
3523 *       N/A
3524 *
3525 ****************************************************************************************************
3526 */
HwlComputeSurfaceAlignmentsMacroTiled(AddrTileMode tileMode,UINT_32 bpp,ADDR_SURFACE_FLAGS flags,UINT_32 mipLevel,UINT_32 numSamples,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const3527 VOID SiLib::HwlComputeSurfaceAlignmentsMacroTiled(
3528     AddrTileMode                      tileMode,           ///< [in] tile mode
3529     UINT_32                           bpp,                ///< [in] bits per pixel
3530     ADDR_SURFACE_FLAGS                flags,              ///< [in] surface flags
3531     UINT_32                           mipLevel,           ///< [in] mip level
3532     UINT_32                           numSamples,         ///< [in] number of samples
3533     ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut                ///< [in,out] Surface output
3534     ) const
3535 {
3536     if ((mipLevel == 0) && (flags.prt))
3537     {
3538         UINT_32 macroTileSize = pOut->blockWidth * pOut->blockHeight * numSamples * bpp / 8;
3539 
3540         if (macroTileSize < PrtTileSize)
3541         {
3542             UINT_32 numMacroTiles = PrtTileSize / macroTileSize;
3543 
3544             ADDR_ASSERT((PrtTileSize % macroTileSize) == 0);
3545 
3546             pOut->pitchAlign *= numMacroTiles;
3547             pOut->baseAlign  *= numMacroTiles;
3548         }
3549     }
3550 }
3551 
3552 /**
3553 ****************************************************************************************************
3554 *   SiLib::InitEquationTable
3555 *
3556 *   @brief
3557 *       Initialize Equation table.
3558 *
3559 *   @return
3560 *       N/A
3561 ****************************************************************************************************
3562 */
InitEquationTable()3563 VOID SiLib::InitEquationTable()
3564 {
3565     ADDR_EQUATION_KEY equationKeyTable[EquationTableSize];
3566     memset(equationKeyTable, 0, sizeof(equationKeyTable));
3567 
3568     memset(m_equationTable, 0, sizeof(m_equationTable));
3569 
3570     memset(m_blockWidth, 0, sizeof(m_blockWidth));
3571 
3572     memset(m_blockHeight, 0, sizeof(m_blockHeight));
3573 
3574     memset(m_blockSlices, 0, sizeof(m_blockSlices));
3575 
3576     // Loop all possible bpp
3577     for (UINT_32 log2ElementBytes = 0; log2ElementBytes < MaxNumElementBytes; log2ElementBytes++)
3578     {
3579         // Get bits per pixel
3580         UINT_32 bpp = 1 << (log2ElementBytes + 3);
3581 
3582         // Loop all possible tile index
3583         for (INT_32 tileIndex = 0; tileIndex < static_cast<INT_32>(m_noOfEntries); tileIndex++)
3584         {
3585             UINT_32 equationIndex = ADDR_INVALID_EQUATION_INDEX;
3586 
3587             TileConfig tileConfig = m_tileTable[tileIndex];
3588 
3589             ADDR_SURFACE_FLAGS flags = {{0}};
3590 
3591             // Compute tile info, hardcode numSamples to 1 because MSAA is not supported
3592             // in swizzle pattern equation
3593             HwlComputeMacroModeIndex(tileIndex, flags, bpp, 1, &tileConfig.info, NULL, NULL);
3594 
3595             // Check if the input is supported
3596             if (IsEquationSupported(bpp, tileConfig, tileIndex, log2ElementBytes) == TRUE)
3597             {
3598                 ADDR_EQUATION_KEY  key   = {{0}};
3599 
3600                 // Generate swizzle equation key from bpp and tile config
3601                 key.fields.log2ElementBytes = log2ElementBytes;
3602                 key.fields.tileMode         = tileConfig.mode;
3603                 // Treat depth micro tile type and non-display micro tile type as the same key
3604                 // because they have the same equation actually
3605                 key.fields.microTileType    = (tileConfig.type == ADDR_DEPTH_SAMPLE_ORDER) ?
3606                                               ADDR_NON_DISPLAYABLE : tileConfig.type;
3607                 key.fields.pipeConfig       = tileConfig.info.pipeConfig;
3608                 key.fields.numBanksLog2     = Log2(tileConfig.info.banks);
3609                 key.fields.bankWidth        = tileConfig.info.bankWidth;
3610                 key.fields.bankHeight       = tileConfig.info.bankHeight;
3611                 key.fields.macroAspectRatio = tileConfig.info.macroAspectRatio;
3612                 key.fields.prt              = ((m_chipFamily == ADDR_CHIP_FAMILY_SI) &&
3613                                                ((1 << tileIndex) & SiPrtTileIndexMask)) ? 1 : 0;
3614 
3615                 // Find in the table if the equation has been built based on the key
3616                 for (UINT_32 i = 0; i < m_numEquations; i++)
3617                 {
3618                     if (key.value == equationKeyTable[i].value)
3619                     {
3620                         equationIndex = i;
3621                         break;
3622                     }
3623                 }
3624 
3625                 // If found, just fill the index into the lookup table and no need
3626                 // to generate the equation again. Otherwise, generate the equation.
3627                 if (equationIndex == ADDR_INVALID_EQUATION_INDEX)
3628                 {
3629                     ADDR_EQUATION equation;
3630                     ADDR_E_RETURNCODE retCode;
3631 
3632                     memset(&equation, 0, sizeof(ADDR_EQUATION));
3633 
3634                     // Generate the equation
3635                     if (IsMicroTiled(tileConfig.mode))
3636                     {
3637                         retCode = ComputeMicroTileEquation(log2ElementBytes,
3638                                                            tileConfig.mode,
3639                                                            tileConfig.type,
3640                                                            &equation);
3641                     }
3642                     else
3643                     {
3644                         retCode = ComputeMacroTileEquation(log2ElementBytes,
3645                                                            tileConfig.mode,
3646                                                            tileConfig.type,
3647                                                            &tileConfig.info,
3648                                                            &equation);
3649                     }
3650                     // Only fill the equation into the table if the return code is ADDR_OK,
3651                     // otherwise if the return code is not ADDR_OK, it indicates this is not
3652                     // a valid input, we do nothing but just fill invalid equation index
3653                     // into the lookup table.
3654                     if (retCode == ADDR_OK)
3655                     {
3656                         equationIndex = m_numEquations;
3657                         ADDR_ASSERT(equationIndex < EquationTableSize);
3658 
3659                         m_blockSlices[equationIndex] = Thickness(tileConfig.mode);
3660 
3661                         if (IsMicroTiled(tileConfig.mode))
3662                         {
3663                             m_blockWidth[equationIndex]  = MicroTileWidth;
3664                             m_blockHeight[equationIndex] = MicroTileHeight;
3665                         }
3666                         else
3667                         {
3668                             const ADDR_TILEINFO* pTileInfo = &tileConfig.info;
3669 
3670                             m_blockWidth[equationIndex]  =
3671                                 HwlGetPipes(pTileInfo) * MicroTileWidth * pTileInfo->bankWidth *
3672                                 pTileInfo->macroAspectRatio;
3673                             m_blockHeight[equationIndex] =
3674                                 MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks /
3675                                 pTileInfo->macroAspectRatio;
3676 
3677                             if (key.fields.prt)
3678                             {
3679                                 UINT_32 macroTileSize =
3680                                     m_blockWidth[equationIndex] * m_blockHeight[equationIndex] *
3681                                     bpp / 8;
3682 
3683                                 if (macroTileSize < PrtTileSize)
3684                                 {
3685                                     UINT_32 numMacroTiles = PrtTileSize / macroTileSize;
3686 
3687                                     ADDR_ASSERT(macroTileSize == (1u << equation.numBits));
3688                                     ADDR_ASSERT((PrtTileSize % macroTileSize) == 0);
3689 
3690                                     UINT_32 numBits = Log2(numMacroTiles);
3691 
3692                                     UINT_32 xStart = Log2(m_blockWidth[equationIndex]) +
3693                                                      log2ElementBytes;
3694 
3695                                     m_blockWidth[equationIndex] *= numMacroTiles;
3696 
3697                                     for (UINT_32 i = 0; i < numBits; i++)
3698                                     {
3699                                         equation.addr[equation.numBits + i].valid = 1;
3700                                         equation.addr[equation.numBits + i].index = xStart + i;
3701                                     }
3702 
3703                                     equation.numBits += numBits;
3704                                 }
3705                             }
3706                         }
3707 
3708                         equationKeyTable[equationIndex] = key;
3709                         m_equationTable[equationIndex]  = equation;
3710 
3711                         m_numEquations++;
3712                     }
3713                 }
3714             }
3715 
3716             // Fill the index into the lookup table, if the combination is not supported
3717             // fill the invalid equation index
3718             m_equationLookupTable[log2ElementBytes][tileIndex] = equationIndex;
3719         }
3720 
3721         if (m_chipFamily == ADDR_CHIP_FAMILY_SI)
3722         {
3723             // For tile index 3 which is shared between PRT depth and uncompressed depth
3724             m_uncompressDepthEqIndex = m_numEquations;
3725 
3726             for (UINT_32 log2ElemBytes = 0; log2ElemBytes < MaxNumElementBytes; log2ElemBytes++)
3727             {
3728                 TileConfig        tileConfig = m_tileTable[3];
3729                 ADDR_EQUATION     equation;
3730                 ADDR_E_RETURNCODE retCode;
3731 
3732                 memset(&equation, 0, sizeof(ADDR_EQUATION));
3733 
3734                 retCode = ComputeMacroTileEquation(log2ElemBytes,
3735                                                    tileConfig.mode,
3736                                                    tileConfig.type,
3737                                                    &tileConfig.info,
3738                                                    &equation);
3739 
3740                 if (retCode == ADDR_OK)
3741                 {
3742                     UINT_32 equationIndex = m_numEquations;
3743                     ADDR_ASSERT(equationIndex < EquationTableSize);
3744 
3745                     m_blockSlices[equationIndex] = 1;
3746 
3747                     const ADDR_TILEINFO* pTileInfo = &tileConfig.info;
3748 
3749                     m_blockWidth[equationIndex]  =
3750                         HwlGetPipes(pTileInfo) * MicroTileWidth * pTileInfo->bankWidth *
3751                         pTileInfo->macroAspectRatio;
3752                     m_blockHeight[equationIndex] =
3753                         MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks /
3754                         pTileInfo->macroAspectRatio;
3755 
3756                     m_equationTable[equationIndex] = equation;
3757 
3758                     m_numEquations++;
3759                 }
3760             }
3761         }
3762     }
3763 }
3764 
3765 /**
3766 ****************************************************************************************************
3767 *   SiLib::IsEquationSupported
3768 *
3769 *   @brief
3770 *       Check if it is supported for given bpp and tile config to generate a equation.
3771 *
3772 *   @return
3773 *       TRUE if supported
3774 ****************************************************************************************************
3775 */
IsEquationSupported(UINT_32 bpp,TileConfig tileConfig,INT_32 tileIndex,UINT_32 elementBytesLog2) const3776 BOOL_32 SiLib::IsEquationSupported(
3777     UINT_32    bpp,             ///< Bits per pixel
3778     TileConfig tileConfig,      ///< Tile config
3779     INT_32     tileIndex,       ///< Tile index
3780     UINT_32    elementBytesLog2 ///< Log2 of element bytes
3781     ) const
3782 {
3783     BOOL_32 supported = TRUE;
3784 
3785     // Linear tile mode is not supported in swizzle pattern equation
3786     if (IsLinear(tileConfig.mode))
3787     {
3788         supported = FALSE;
3789     }
3790     // These tile modes are for Tex2DArray and Tex3D which has depth (num_slice > 1) use,
3791     // which is not supported in swizzle pattern equation due to slice rotation
3792     else if ((tileConfig.mode == ADDR_TM_2D_TILED_THICK)  ||
3793              (tileConfig.mode == ADDR_TM_2D_TILED_XTHICK) ||
3794              (tileConfig.mode == ADDR_TM_3D_TILED_THIN1)  ||
3795              (tileConfig.mode == ADDR_TM_3D_TILED_THICK)  ||
3796              (tileConfig.mode == ADDR_TM_3D_TILED_XTHICK))
3797     {
3798         supported = FALSE;
3799     }
3800     // Only 8bpp(stencil), 16bpp and 32bpp is supported for depth
3801     else if ((tileConfig.type == ADDR_DEPTH_SAMPLE_ORDER) && (bpp > 32))
3802     {
3803         supported = FALSE;
3804     }
3805     // Tile split is not supported in swizzle pattern equation
3806     else if (IsMacroTiled(tileConfig.mode))
3807     {
3808         UINT_32 thickness = Thickness(tileConfig.mode);
3809         if (((bpp >> 3) * MicroTilePixels * thickness) > tileConfig.info.tileSplitBytes)
3810         {
3811             supported = FALSE;
3812         }
3813 
3814         if ((supported == TRUE) && (m_chipFamily == ADDR_CHIP_FAMILY_SI))
3815         {
3816             supported = m_EquationSupport[tileIndex][elementBytesLog2];
3817         }
3818     }
3819 
3820     return supported;
3821 }
3822 
3823 } // V1
3824 } // Addr
3825