• 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  addrcommon.h
30 * @brief Contains the helper function and constants
31 ***************************************************************************************************
32 */
33 
34 #ifndef __ADDR_COMMON_H__
35 #define __ADDR_COMMON_H__
36 
37 #include "addrinterface.h"
38 
39 
40 // ADDR_LNX_KERNEL_BUILD is for internal build
41 // Moved from addrinterface.h so __KERNEL__ is not needed any more
42 #if ADDR_LNX_KERNEL_BUILD // || (defined(__GNUC__) && defined(__KERNEL__))
43     #include "lnx_common_defs.h" // ported from cmmqs
44 #elif !defined(__APPLE__)
45     #include <stdlib.h>
46     #include <string.h>
47 #endif
48 
49 ///////////////////////////////////////////////////////////////////////////////////////////////////
50 // Common constants
51 ///////////////////////////////////////////////////////////////////////////////////////////////////
52 static const UINT_32 MicroTileWidth      = 8;       ///< Micro tile width, for 1D and 2D tiling
53 static const UINT_32 MicroTileHeight     = 8;       ///< Micro tile height, for 1D and 2D tiling
54 static const UINT_32 ThickTileThickness  = 4;       ///< Micro tile thickness, for THICK modes
55 static const UINT_32 XThickTileThickness = 8;       ///< Extra thick tiling thickness
56 static const UINT_32 PowerSaveTileBytes  = 64;      ///< Nuber of bytes per tile for power save 64
57 static const UINT_32 CmaskCacheBits      = 1024;    ///< Number of bits for CMASK cache
58 static const UINT_32 CmaskElemBits       = 4;       ///< Number of bits for CMASK element
59 static const UINT_32 HtileCacheBits      = 16384;   ///< Number of bits for HTILE cache 512*32
60 
61 static const UINT_32 MicroTilePixels     = MicroTileWidth * MicroTileHeight;
62 
63 static const INT_32 TileIndexInvalid        = TILEINDEX_INVALID;
64 static const INT_32 TileIndexLinearGeneral  = TILEINDEX_LINEAR_GENERAL;
65 static const INT_32 TileIndexNoMacroIndex   = -3;
66 
67 ///////////////////////////////////////////////////////////////////////////////////////////////////
68 // Common macros
69 ///////////////////////////////////////////////////////////////////////////////////////////////////
70 #define BITS_PER_BYTE 8
71 #define BITS_TO_BYTES(x) ( ((x) + (BITS_PER_BYTE-1)) / BITS_PER_BYTE )
72 #define BYTES_TO_BITS(x) ( (x) * BITS_PER_BYTE )
73 
74 /// Helper macros to select a single bit from an int (undefined later in section)
75 #define _BIT(v,b)      (((v) >> (b) ) & 1)
76 
77 /**
78 ***************************************************************************************************
79 * @brief Enums to identify AddrLib type
80 ***************************************************************************************************
81 */
82 enum AddrLibClass
83 {
84     BASE_ADDRLIB = 0x0,
85     R600_ADDRLIB = 0x6,
86     R800_ADDRLIB = 0x8,
87     SI_ADDRLIB   = 0xa,
88     CI_ADDRLIB   = 0xb,
89 };
90 
91 /**
92 ***************************************************************************************************
93 * AddrChipFamily
94 *
95 *   @brief
96 *       Neutral enums that specifies chip family.
97 *
98 ***************************************************************************************************
99 */
100 enum AddrChipFamily
101 {
102     ADDR_CHIP_FAMILY_IVLD,    ///< Invalid family
103     ADDR_CHIP_FAMILY_R6XX,
104     ADDR_CHIP_FAMILY_R7XX,
105     ADDR_CHIP_FAMILY_R8XX,
106     ADDR_CHIP_FAMILY_NI,
107     ADDR_CHIP_FAMILY_SI,
108     ADDR_CHIP_FAMILY_CI,
109     ADDR_CHIP_FAMILY_VI,
110 };
111 
112 /**
113 ***************************************************************************************************
114 * ADDR_CONFIG_FLAGS
115 *
116 *   @brief
117 *       This structure is used to set addr configuration flags.
118 ***************************************************************************************************
119 */
120 union ADDR_CONFIG_FLAGS
121 {
122     struct
123     {
124         /// Clients do not need to set these flags except forceLinearAligned.
125         /// There flags are set up by AddrLib inside thru AddrInitGlobalParamsFromRegister
126         UINT_32 optimalBankSwap        : 1;    ///< New bank tiling for RV770 only
127         UINT_32 noCubeMipSlicesPad     : 1;    ///< Disables faces padding for cubemap mipmaps
128         UINT_32 fillSizeFields         : 1;    ///< If clients fill size fields in all input and
129                                                ///  output structure
130         UINT_32 ignoreTileInfo         : 1;    ///< Don't use tile info structure
131         UINT_32 useTileIndex           : 1;    ///< Make tileIndex field in input valid
132         UINT_32 useCombinedSwizzle     : 1;    ///< Use combined swizzle
133         UINT_32 checkLast2DLevel       : 1;    ///< Check the last 2D mip sub level
134         UINT_32 useHtileSliceAlign     : 1;    ///< Do htile single slice alignment
135         UINT_32 degradeBaseLevel       : 1;    ///< Degrade to 1D modes automatically for base level
136         UINT_32 allowLargeThickTile    : 1;    ///< Allow 64*thickness*bytesPerPixel > rowSize
137         UINT_32 reserved               : 22;   ///< Reserved bits for future use
138     };
139 
140     UINT_32 value;
141 };
142 
143 ///////////////////////////////////////////////////////////////////////////////////////////////////
144 // Platform specific debug break defines
145 ///////////////////////////////////////////////////////////////////////////////////////////////////
146 #if DEBUG
147     #if defined(__GNUC__)
148         #define ADDR_DBG_BREAK()
149     #elif defined(__APPLE__)
150         #define ADDR_DBG_BREAK()    { IOPanic("");}
151     #else
152         #define ADDR_DBG_BREAK()    { __debugbreak(); }
153     #endif
154 #else
155     #define ADDR_DBG_BREAK()
156 #endif
157 ///////////////////////////////////////////////////////////////////////////////////////////////////
158 
159 ///////////////////////////////////////////////////////////////////////////////////////////////////
160 // Debug assertions used in AddrLib
161 ///////////////////////////////////////////////////////////////////////////////////////////////////
162 #if DEBUG
163 #define ADDR_ASSERT(__e) if ( !((__e) ? TRUE : FALSE)) { ADDR_DBG_BREAK(); }
164 #define ADDR_ASSERT_ALWAYS() ADDR_DBG_BREAK()
165 #define ADDR_UNHANDLED_CASE() ADDR_ASSERT(!"Unhandled case")
166 #define ADDR_NOT_IMPLEMENTED() ADDR_ASSERT(!"Not implemented");
167 #else //DEBUG
168 #define ADDR_ASSERT(__e)
169 #define ADDR_ASSERT_ALWAYS()
170 #define ADDR_UNHANDLED_CASE()
171 #define ADDR_NOT_IMPLEMENTED()
172 #endif //DEBUG
173 ///////////////////////////////////////////////////////////////////////////////////////////////////
174 
175 ///////////////////////////////////////////////////////////////////////////////////////////////////
176 // Debug print macro from legacy address library
177 ///////////////////////////////////////////////////////////////////////////////////////////////////
178 #if DEBUG
179 
180 #define ADDR_PRNT(a)    AddrObject::DebugPrint a
181 
182 /// @brief Macro for reporting informational messages
183 /// @ingroup util
184 ///
185 /// This macro optionally prints an informational message to stdout.
186 /// The first parameter is a condition -- if it is true, nothing is done.
187 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
188 /// starting with a string. This is passed to printf() or an equivalent
189 /// in order to format the informational message. For example,
190 /// ADDR_INFO(0, ("test %d",3) ); prints out "test 3".
191 ///
192 #define ADDR_INFO(cond, a)         \
193 { if (!(cond)) { ADDR_PRNT(a); } }
194 
195 
196 /// @brief Macro for reporting error warning messages
197 /// @ingroup util
198 ///
199 /// This macro optionally prints an error warning message to stdout,
200 /// followed by the file name and line number where the macro was called.
201 /// The first parameter is a condition -- if it is true, nothing is done.
202 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
203 /// starting with a string. This is passed to printf() or an equivalent
204 /// in order to format the informational message. For example,
205 /// ADDR_WARN(0, ("test %d",3) ); prints out "test 3" followed by
206 /// a second line with the file name and line number.
207 ///
208 #define ADDR_WARN(cond, a)         \
209 { if (!(cond))                     \
210   { ADDR_PRNT(a);                  \
211     ADDR_PRNT(("  WARNING in file %s, line %d\n", __FILE__, __LINE__)); \
212 } }
213 
214 
215 /// @brief Macro for reporting fatal error conditions
216 /// @ingroup util
217 ///
218 /// This macro optionally stops execution of the current routine
219 /// after printing an error warning message to stdout,
220 /// followed by the file name and line number where the macro was called.
221 /// The first parameter is a condition -- if it is true, nothing is done.
222 /// The second pararmeter MUST be a parenthesis-enclosed list of arguments,
223 /// starting with a string. This is passed to printf() or an equivalent
224 /// in order to format the informational message. For example,
225 /// ADDR_EXIT(0, ("test %d",3) ); prints out "test 3" followed by
226 /// a second line with the file name and line number, then stops execution.
227 ///
228 #define ADDR_EXIT(cond, a)         \
229 { if (!(cond))                     \
230   { ADDR_PRNT(a); ADDR_DBG_BREAK();\
231 } }
232 
233 #else // DEBUG
234 
235 #define ADDRDPF 1 ? (void)0 : (void)
236 
237 #define ADDR_PRNT(a)
238 
239 #define ADDR_DBG_BREAK()
240 
241 #define ADDR_INFO(cond, a)
242 
243 #define ADDR_WARN(cond, a)
244 
245 #define ADDR_EXIT(cond, a)
246 
247 #endif // DEBUG
248 ///////////////////////////////////////////////////////////////////////////////////////////////////
249 
250 ///////////////////////////////////////////////////////////////////////////////////////////////////
251 // Misc helper functions
252 ////////////////////////////////////////////////////////////////////////////////////////////////////
253 
254 /**
255 ***************************************************************************************************
256 *   AddrXorReduce
257 *
258 *   @brief
259 *       Xor the right-side numberOfBits bits of x.
260 ***************************************************************************************************
261 */
XorReduce(UINT_32 x,UINT_32 numberOfBits)262 static inline UINT_32 XorReduce(
263     UINT_32 x,
264     UINT_32 numberOfBits)
265 {
266     UINT_32 i;
267     UINT_32 result = x & 1;
268 
269     for (i=1; i<numberOfBits; i++)
270     {
271         result ^= ((x>>i) & 1);
272     }
273 
274     return result;
275 }
276 
277 /**
278 ***************************************************************************************************
279 *   IsPow2
280 *
281 *   @brief
282 *       Check if the size (UINT_32) is pow 2
283 ***************************************************************************************************
284 */
IsPow2(UINT_32 dim)285 static inline UINT_32 IsPow2(
286     UINT_32 dim)        ///< [in] dimension of miplevel
287 {
288     ADDR_ASSERT(dim > 0);
289     return !(dim & (dim - 1));
290 }
291 
292 /**
293 ***************************************************************************************************
294 *   IsPow2
295 *
296 *   @brief
297 *       Check if the size (UINT_64) is pow 2
298 ***************************************************************************************************
299 */
IsPow2(UINT_64 dim)300 static inline UINT_64 IsPow2(
301     UINT_64 dim)        ///< [in] dimension of miplevel
302 {
303     ADDR_ASSERT(dim > 0);
304     return !(dim & (dim - 1));
305 }
306 
307 /**
308 ***************************************************************************************************
309 *   ByteAlign
310 *
311 *   @brief
312 *       Align UINT_32 "x" to "align" alignment, "align" should be power of 2
313 ***************************************************************************************************
314 */
PowTwoAlign(UINT_32 x,UINT_32 align)315 static inline UINT_32 PowTwoAlign(
316     UINT_32 x,
317     UINT_32 align)
318 {
319     //
320     // Assert that x is a power of two.
321     //
322     ADDR_ASSERT(IsPow2(align));
323     return (x + (align - 1)) & (~(align - 1));
324 }
325 
326 /**
327 ***************************************************************************************************
328 *   ByteAlign
329 *
330 *   @brief
331 *       Align UINT_64 "x" to "align" alignment, "align" should be power of 2
332 ***************************************************************************************************
333 */
PowTwoAlign(UINT_64 x,UINT_64 align)334 static inline UINT_64 PowTwoAlign(
335     UINT_64 x,
336     UINT_64 align)
337 {
338     //
339     // Assert that x is a power of two.
340     //
341     ADDR_ASSERT(IsPow2(align));
342     return (x + (align - 1)) & (~(align - 1));
343 }
344 
345 /**
346 ***************************************************************************************************
347 *   Min
348 *
349 *   @brief
350 *       Get the min value between two unsigned values
351 ***************************************************************************************************
352 */
Min(UINT_32 value1,UINT_32 value2)353 static inline UINT_32 Min(
354     UINT_32 value1,
355     UINT_32 value2)
356 {
357     return ((value1 < (value2)) ? (value1) : value2);
358 }
359 
360 /**
361 ***************************************************************************************************
362 *   Min
363 *
364 *   @brief
365 *       Get the min value between two signed values
366 ***************************************************************************************************
367 */
Min(INT_32 value1,INT_32 value2)368 static inline INT_32 Min(
369     INT_32 value1,
370     INT_32 value2)
371 {
372     return ((value1 < (value2)) ? (value1) : value2);
373 }
374 
375 /**
376 ***************************************************************************************************
377 *   Max
378 *
379 *   @brief
380 *       Get the max value between two unsigned values
381 ***************************************************************************************************
382 */
Max(UINT_32 value1,UINT_32 value2)383 static inline UINT_32 Max(
384     UINT_32 value1,
385     UINT_32 value2)
386 {
387     return ((value1 > (value2)) ? (value1) : value2);
388 }
389 
390 /**
391 ***************************************************************************************************
392 *   Max
393 *
394 *   @brief
395 *       Get the max value between two signed values
396 ***************************************************************************************************
397 */
Max(INT_32 value1,INT_32 value2)398 static inline INT_32 Max(
399     INT_32 value1,
400     INT_32 value2)
401 {
402     return ((value1 > (value2)) ? (value1) : value2);
403 }
404 
405 /**
406 ***************************************************************************************************
407 *   NextPow2
408 *
409 *   @brief
410 *       Compute the mipmap's next level dim size
411 ***************************************************************************************************
412 */
NextPow2(UINT_32 dim)413 static inline UINT_32 NextPow2(
414     UINT_32 dim)        ///< [in] dimension of miplevel
415 {
416     UINT_32 newDim;
417 
418     newDim = 1;
419 
420     if (dim > 0x7fffffff)
421     {
422         ADDR_ASSERT_ALWAYS();
423         newDim = 0x80000000;
424     }
425     else
426     {
427         while (newDim < dim)
428         {
429             newDim <<= 1;
430         }
431     }
432 
433     return newDim;
434 }
435 
436 /**
437 ***************************************************************************************************
438 *   Log2
439 *
440 *   @brief
441 *       Compute log of base 2
442 ***************************************************************************************************
443 */
Log2(UINT_32 x)444 static inline UINT_32 Log2(
445     UINT_32 x)      ///< [in] the value should calculate log based 2
446 {
447     UINT_32 y;
448 
449     //
450     // Assert that x is a power of two.
451     //
452     ADDR_ASSERT(IsPow2(x));
453 
454     y = 0;
455     while (x > 1)
456     {
457         x >>= 1;
458         y++;
459     }
460 
461     return y;
462 }
463 
464 /**
465 ***************************************************************************************************
466 *   QLog2
467 *
468 *   @brief
469 *       Compute log of base 2 quickly (<= 16)
470 ***************************************************************************************************
471 */
QLog2(UINT_32 x)472 static inline UINT_32 QLog2(
473     UINT_32 x)      ///< [in] the value should calculate log based 2
474 {
475     ADDR_ASSERT(x <= 16);
476 
477     UINT_32 y = 0;
478 
479     switch (x)
480     {
481         case 1:
482             y = 0;
483             break;
484         case 2:
485             y = 1;
486             break;
487         case 4:
488             y = 2;
489             break;
490         case 8:
491             y = 3;
492             break;
493         case 16:
494             y = 4;
495             break;
496         default:
497             ADDR_ASSERT_ALWAYS();
498     }
499 
500     return y;
501 }
502 
503 /**
504 ***************************************************************************************************
505 *   SafeAssign
506 *
507 *   @brief
508 *       NULL pointer safe assignment
509 ***************************************************************************************************
510 */
SafeAssign(UINT_32 * pLVal,UINT_32 rVal)511 static inline VOID SafeAssign(
512     UINT_32*    pLVal,  ///< [in] Pointer to left val
513     UINT_32     rVal)   ///< [in] Right value
514 {
515     if (pLVal)
516     {
517         *pLVal = rVal;
518     }
519 }
520 
521 /**
522 ***************************************************************************************************
523 *   SafeAssign
524 *
525 *   @brief
526 *       NULL pointer safe assignment for 64bit values
527 ***************************************************************************************************
528 */
SafeAssign(UINT_64 * pLVal,UINT_64 rVal)529 static inline VOID SafeAssign(
530     UINT_64*    pLVal,  ///< [in] Pointer to left val
531     UINT_64     rVal)   ///< [in] Right value
532 {
533     if (pLVal)
534     {
535         *pLVal = rVal;
536     }
537 }
538 
539 /**
540 ***************************************************************************************************
541 *   SafeAssign
542 *
543 *   @brief
544 *       NULL pointer safe assignment for AddrTileMode
545 ***************************************************************************************************
546 */
SafeAssign(AddrTileMode * pLVal,AddrTileMode rVal)547 static inline VOID SafeAssign(
548     AddrTileMode*    pLVal, ///< [in] Pointer to left val
549     AddrTileMode     rVal)  ///< [in] Right value
550 {
551     if (pLVal)
552     {
553         *pLVal = rVal;
554     }
555 }
556 
557 #endif // __ADDR_COMMON_H__
558 
559