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 addrlib.cpp
30 * @brief Contains the implementation for the Addr::Lib class.
31 ****************************************************************************************************
32 */
33
34 #include "addrinterface.h"
35 #include "addrlib.h"
36 #include "addrcommon.h"
37
38 #if defined(__APPLE__)
39
div64_32(UINT_64 n,UINT_32 base)40 UINT_32 div64_32(UINT_64 n, UINT_32 base)
41 {
42 UINT_64 rem = n;
43 UINT_64 b = base;
44 UINT_64 res, d = 1;
45 UINT_32 high = rem >> 32;
46
47 res = 0;
48 if (high >= base)
49 {
50 high /= base;
51 res = (UINT_64) high << 32;
52 rem -= (UINT_64) (high * base) << 32;
53 }
54
55 while (((INT_64)b > 0) && (b < rem))
56 {
57 b = b + b;
58 d = d + d;
59 }
60
61 do
62 {
63 if (rem >= b)
64 {
65 rem -= b;
66 res += d;
67 }
68 b >>= 1;
69 d >>= 1;
70 } while (d);
71
72 n = res;
73 return rem;
74 }
75
76 extern "C"
__umoddi3(UINT_64 n,UINT_32 base)77 UINT_32 __umoddi3(UINT_64 n, UINT_32 base)
78 {
79 return div64_32(n, base);
80 }
81
82 #endif // __APPLE__
83
84 namespace Addr
85 {
86
87 ////////////////////////////////////////////////////////////////////////////////////////////////////
88 // Constructor/Destructor
89 ////////////////////////////////////////////////////////////////////////////////////////////////////
90
91 /**
92 ****************************************************************************************************
93 * Lib::Lib
94 *
95 * @brief
96 * Constructor for the AddrLib class
97 *
98 ****************************************************************************************************
99 */
Lib()100 Lib::Lib() :
101 m_class(BASE_ADDRLIB),
102 m_chipFamily(ADDR_CHIP_FAMILY_IVLD),
103 m_chipRevision(0),
104 m_version(ADDRLIB_VERSION),
105 m_pipes(0),
106 m_banks(0),
107 m_pipeInterleaveBytes(0),
108 m_rowSize(0),
109 m_minPitchAlignPixels(1),
110 m_maxSamples(8),
111 m_pElemLib(NULL)
112 {
113 m_configFlags.value = 0;
114 }
115
116 /**
117 ****************************************************************************************************
118 * Lib::Lib
119 *
120 * @brief
121 * Constructor for the AddrLib class with hClient as parameter
122 *
123 ****************************************************************************************************
124 */
Lib(const Client * pClient)125 Lib::Lib(const Client* pClient) :
126 Object(pClient),
127 m_class(BASE_ADDRLIB),
128 m_chipFamily(ADDR_CHIP_FAMILY_IVLD),
129 m_chipRevision(0),
130 m_version(ADDRLIB_VERSION),
131 m_pipes(0),
132 m_banks(0),
133 m_pipeInterleaveBytes(0),
134 m_rowSize(0),
135 m_minPitchAlignPixels(1),
136 m_maxSamples(8),
137 m_pElemLib(NULL)
138 {
139 m_configFlags.value = 0;
140 }
141
142 /**
143 ****************************************************************************************************
144 * Lib::~AddrLib
145 *
146 * @brief
147 * Destructor for the AddrLib class
148 *
149 ****************************************************************************************************
150 */
~Lib()151 Lib::~Lib()
152 {
153 if (m_pElemLib)
154 {
155 delete m_pElemLib;
156 m_pElemLib = NULL;
157 }
158 }
159
160
161 ////////////////////////////////////////////////////////////////////////////////////////////////////
162 // Initialization/Helper
163 ////////////////////////////////////////////////////////////////////////////////////////////////////
164
165 /**
166 ****************************************************************************************************
167 * Lib::Create
168 *
169 * @brief
170 * Creates and initializes AddrLib object.
171 *
172 * @return
173 * ADDR_E_RETURNCODE
174 ****************************************************************************************************
175 */
Create(const ADDR_CREATE_INPUT * pCreateIn,ADDR_CREATE_OUTPUT * pCreateOut)176 ADDR_E_RETURNCODE Lib::Create(
177 const ADDR_CREATE_INPUT* pCreateIn, ///< [in] pointer to ADDR_CREATE_INPUT
178 ADDR_CREATE_OUTPUT* pCreateOut) ///< [out] pointer to ADDR_CREATE_OUTPUT
179 {
180 Lib* pLib = NULL;
181 ADDR_E_RETURNCODE returnCode = ADDR_OK;
182
183 if (pCreateIn->createFlags.fillSizeFields == TRUE)
184 {
185 if ((pCreateIn->size != sizeof(ADDR_CREATE_INPUT)) ||
186 (pCreateOut->size != sizeof(ADDR_CREATE_OUTPUT)))
187 {
188 returnCode = ADDR_PARAMSIZEMISMATCH;
189 }
190 }
191
192 if ((returnCode == ADDR_OK) &&
193 (pCreateIn->callbacks.allocSysMem != NULL) &&
194 (pCreateIn->callbacks.freeSysMem != NULL))
195 {
196 Client client = {
197 pCreateIn->hClient,
198 pCreateIn->callbacks
199 };
200
201 switch (pCreateIn->chipEngine)
202 {
203 case CIASICIDGFXENGINE_SOUTHERNISLAND:
204 switch (pCreateIn->chipFamily)
205 {
206 case FAMILY_SI:
207 pLib = SiHwlInit(&client);
208 break;
209 case FAMILY_VI:
210 case FAMILY_CZ: // VI based fusion(carrizo)
211 case FAMILY_CI:
212 case FAMILY_KV: // CI based fusion
213 pLib = CiHwlInit(&client);
214 break;
215 default:
216 ADDR_ASSERT_ALWAYS();
217 break;
218 }
219 break;
220 case CIASICIDGFXENGINE_ARCTICISLAND:
221 switch (pCreateIn->chipFamily)
222 {
223 case FAMILY_AI:
224 case FAMILY_RV:
225 pLib = Gfx9HwlInit(&client);
226 break;
227 default:
228 ADDR_ASSERT_ALWAYS();
229 break;
230 }
231 break;
232 default:
233 ADDR_ASSERT_ALWAYS();
234 break;
235 }
236 }
237
238 if (pLib != NULL)
239 {
240 BOOL_32 initValid;
241
242 // Pass createFlags to configFlags first since these flags may be overwritten
243 pLib->m_configFlags.noCubeMipSlicesPad = pCreateIn->createFlags.noCubeMipSlicesPad;
244 pLib->m_configFlags.fillSizeFields = pCreateIn->createFlags.fillSizeFields;
245 pLib->m_configFlags.useTileIndex = pCreateIn->createFlags.useTileIndex;
246 pLib->m_configFlags.useCombinedSwizzle = pCreateIn->createFlags.useCombinedSwizzle;
247 pLib->m_configFlags.checkLast2DLevel = pCreateIn->createFlags.checkLast2DLevel;
248 pLib->m_configFlags.useHtileSliceAlign = pCreateIn->createFlags.useHtileSliceAlign;
249 pLib->m_configFlags.allowLargeThickTile = pCreateIn->createFlags.allowLargeThickTile;
250 pLib->m_configFlags.disableLinearOpt = FALSE;
251
252 pLib->SetChipFamily(pCreateIn->chipFamily, pCreateIn->chipRevision);
253
254 pLib->SetMinPitchAlignPixels(pCreateIn->minPitchAlignPixels);
255
256 // Global parameters initialized and remaining configFlags bits are set as well
257 initValid = pLib->HwlInitGlobalParams(pCreateIn);
258
259 if (initValid)
260 {
261 pLib->m_pElemLib = ElemLib::Create(pLib);
262 }
263 else
264 {
265 pLib->m_pElemLib = NULL; // Don't go on allocating element lib
266 returnCode = ADDR_INVALIDGBREGVALUES;
267 }
268
269 if (pLib->m_pElemLib == NULL)
270 {
271 delete pLib;
272 pLib = NULL;
273 ADDR_ASSERT_ALWAYS();
274 }
275 else
276 {
277 pLib->m_pElemLib->SetConfigFlags(pLib->m_configFlags);
278 }
279 }
280
281 pCreateOut->hLib = pLib;
282
283 if ((pLib != NULL) &&
284 (returnCode == ADDR_OK))
285 {
286 pCreateOut->numEquations =
287 pLib->HwlGetEquationTableInfo(&pCreateOut->pEquationTable);
288 }
289
290 if ((pLib == NULL) &&
291 (returnCode == ADDR_OK))
292 {
293 // Unknown failures, we return the general error code
294 returnCode = ADDR_ERROR;
295 }
296
297 return returnCode;
298 }
299
300 /**
301 ****************************************************************************************************
302 * Lib::SetChipFamily
303 *
304 * @brief
305 * Convert familyID defined in atiid.h to ChipFamily and set m_chipFamily/m_chipRevision
306 * @return
307 * N/A
308 ****************************************************************************************************
309 */
SetChipFamily(UINT_32 uChipFamily,UINT_32 uChipRevision)310 VOID Lib::SetChipFamily(
311 UINT_32 uChipFamily, ///< [in] chip family defined in atiih.h
312 UINT_32 uChipRevision) ///< [in] chip revision defined in "asic_family"_id.h
313 {
314 ChipFamily family = HwlConvertChipFamily(uChipFamily, uChipRevision);
315
316 ADDR_ASSERT(family != ADDR_CHIP_FAMILY_IVLD);
317
318 m_chipFamily = family;
319 m_chipRevision = uChipRevision;
320 }
321
322 /**
323 ****************************************************************************************************
324 * Lib::SetMinPitchAlignPixels
325 *
326 * @brief
327 * Set m_minPitchAlignPixels with input param
328 *
329 * @return
330 * N/A
331 ****************************************************************************************************
332 */
SetMinPitchAlignPixels(UINT_32 minPitchAlignPixels)333 VOID Lib::SetMinPitchAlignPixels(
334 UINT_32 minPitchAlignPixels) ///< [in] minmum pitch alignment in pixels
335 {
336 m_minPitchAlignPixels = (minPitchAlignPixels == 0) ? 1 : minPitchAlignPixels;
337 }
338
339 /**
340 ****************************************************************************************************
341 * Lib::GetLib
342 *
343 * @brief
344 * Get AddrLib pointer
345 *
346 * @return
347 * An AddrLib class pointer
348 ****************************************************************************************************
349 */
GetLib(ADDR_HANDLE hLib)350 Lib* Lib::GetLib(
351 ADDR_HANDLE hLib) ///< [in] handle of ADDR_HANDLE
352 {
353 return static_cast<Addr::Lib*>(hLib);
354 }
355
356 /**
357 ****************************************************************************************************
358 * Lib::GetMaxAlignments
359 *
360 * @brief
361 * Gets maximum alignments
362 *
363 * @return
364 * ADDR_E_RETURNCODE
365 ****************************************************************************************************
366 */
GetMaxAlignments(ADDR_GET_MAX_ALIGNMENTS_OUTPUT * pOut) const367 ADDR_E_RETURNCODE Lib::GetMaxAlignments(
368 ADDR_GET_MAX_ALIGNMENTS_OUTPUT* pOut ///< [out] output structure
369 ) const
370 {
371 ADDR_E_RETURNCODE returnCode = ADDR_OK;
372
373 if (GetFillSizeFieldsFlags() == TRUE)
374 {
375 if (pOut->size != sizeof(ADDR_GET_MAX_ALIGNMENTS_OUTPUT))
376 {
377 returnCode = ADDR_PARAMSIZEMISMATCH;
378 }
379 }
380
381 if (returnCode == ADDR_OK)
382 {
383 returnCode = HwlGetMaxAlignments(pOut);
384 }
385
386 return returnCode;
387 }
388
389 /**
390 ****************************************************************************************************
391 * Lib::Bits2Number
392 *
393 * @brief
394 * Cat a array of binary bit to a number
395 *
396 * @return
397 * The number combined with the array of bits
398 ****************************************************************************************************
399 */
Bits2Number(UINT_32 bitNum,...)400 UINT_32 Lib::Bits2Number(
401 UINT_32 bitNum, ///< [in] how many bits
402 ...) ///< [in] varaible bits value starting from MSB
403 {
404 UINT_32 number = 0;
405 UINT_32 i;
406 va_list bits_ptr;
407
408 va_start(bits_ptr, bitNum);
409
410 for(i = 0; i < bitNum; i++)
411 {
412 number |= va_arg(bits_ptr, UINT_32);
413 number <<= 1;
414 }
415
416 number >>= 1;
417
418 va_end(bits_ptr);
419
420 return number;
421 }
422
423
424 ////////////////////////////////////////////////////////////////////////////////////////////////////
425 // Element lib
426 ////////////////////////////////////////////////////////////////////////////////////////////////////
427
428
429 /**
430 ****************************************************************************************************
431 * Lib::Flt32ToColorPixel
432 *
433 * @brief
434 * Convert a FLT_32 value to a depth/stencil pixel value
435 * @return
436 * ADDR_E_RETURNCODE
437 ****************************************************************************************************
438 */
Flt32ToDepthPixel(const ELEM_FLT32TODEPTHPIXEL_INPUT * pIn,ELEM_FLT32TODEPTHPIXEL_OUTPUT * pOut) const439 ADDR_E_RETURNCODE Lib::Flt32ToDepthPixel(
440 const ELEM_FLT32TODEPTHPIXEL_INPUT* pIn,
441 ELEM_FLT32TODEPTHPIXEL_OUTPUT* pOut) const
442 {
443 ADDR_E_RETURNCODE returnCode = ADDR_OK;
444
445 if (GetFillSizeFieldsFlags() == TRUE)
446 {
447 if ((pIn->size != sizeof(ELEM_FLT32TODEPTHPIXEL_INPUT)) ||
448 (pOut->size != sizeof(ELEM_FLT32TODEPTHPIXEL_OUTPUT)))
449 {
450 returnCode = ADDR_PARAMSIZEMISMATCH;
451 }
452 }
453
454 if (returnCode == ADDR_OK)
455 {
456 GetElemLib()->Flt32ToDepthPixel(pIn->format, pIn->comps, pOut->pPixel);
457
458 UINT_32 depthBase = 0;
459 UINT_32 stencilBase = 0;
460 UINT_32 depthBits = 0;
461 UINT_32 stencilBits = 0;
462
463 switch (pIn->format)
464 {
465 case ADDR_DEPTH_16:
466 depthBits = 16;
467 break;
468 case ADDR_DEPTH_X8_24:
469 case ADDR_DEPTH_8_24:
470 case ADDR_DEPTH_X8_24_FLOAT:
471 case ADDR_DEPTH_8_24_FLOAT:
472 depthBase = 8;
473 depthBits = 24;
474 stencilBits = 8;
475 break;
476 case ADDR_DEPTH_32_FLOAT:
477 depthBits = 32;
478 break;
479 case ADDR_DEPTH_X24_8_32_FLOAT:
480 depthBase = 8;
481 depthBits = 32;
482 stencilBits = 8;
483 break;
484 default:
485 break;
486 }
487
488 // Overwrite base since R800 has no "tileBase"
489 if (GetElemLib()->IsDepthStencilTilePlanar() == FALSE)
490 {
491 depthBase = 0;
492 stencilBase = 0;
493 }
494
495 depthBase *= 64;
496 stencilBase *= 64;
497
498 pOut->stencilBase = stencilBase;
499 pOut->depthBase = depthBase;
500 pOut->depthBits = depthBits;
501 pOut->stencilBits = stencilBits;
502 }
503
504 return returnCode;
505 }
506
507 /**
508 ****************************************************************************************************
509 * Lib::Flt32ToColorPixel
510 *
511 * @brief
512 * Convert a FLT_32 value to a red/green/blue/alpha pixel value
513 * @return
514 * ADDR_E_RETURNCODE
515 ****************************************************************************************************
516 */
Flt32ToColorPixel(const ELEM_FLT32TOCOLORPIXEL_INPUT * pIn,ELEM_FLT32TOCOLORPIXEL_OUTPUT * pOut) const517 ADDR_E_RETURNCODE Lib::Flt32ToColorPixel(
518 const ELEM_FLT32TOCOLORPIXEL_INPUT* pIn,
519 ELEM_FLT32TOCOLORPIXEL_OUTPUT* pOut) const
520 {
521 ADDR_E_RETURNCODE returnCode = ADDR_OK;
522
523 if (GetFillSizeFieldsFlags() == TRUE)
524 {
525 if ((pIn->size != sizeof(ELEM_FLT32TOCOLORPIXEL_INPUT)) ||
526 (pOut->size != sizeof(ELEM_FLT32TOCOLORPIXEL_OUTPUT)))
527 {
528 returnCode = ADDR_PARAMSIZEMISMATCH;
529 }
530 }
531
532 if (returnCode == ADDR_OK)
533 {
534 GetElemLib()->Flt32ToColorPixel(pIn->format,
535 pIn->surfNum,
536 pIn->surfSwap,
537 pIn->comps,
538 pOut->pPixel);
539 }
540
541 return returnCode;
542 }
543
544
545 /**
546 ****************************************************************************************************
547 * Lib::GetExportNorm
548 *
549 * @brief
550 * Check one format can be EXPORT_NUM
551 * @return
552 * TRUE if EXPORT_NORM can be used
553 ****************************************************************************************************
554 */
GetExportNorm(const ELEM_GETEXPORTNORM_INPUT * pIn) const555 BOOL_32 Lib::GetExportNorm(
556 const ELEM_GETEXPORTNORM_INPUT* pIn) const
557 {
558 ADDR_E_RETURNCODE returnCode = ADDR_OK;
559
560 BOOL_32 enabled = FALSE;
561
562 if (GetFillSizeFieldsFlags() == TRUE)
563 {
564 if (pIn->size != sizeof(ELEM_GETEXPORTNORM_INPUT))
565 {
566 returnCode = ADDR_PARAMSIZEMISMATCH;
567 }
568 }
569
570 if (returnCode == ADDR_OK)
571 {
572 enabled = GetElemLib()->PixGetExportNorm(pIn->format, pIn->num, pIn->swap);
573 }
574
575 return enabled;
576 }
577
578 } // Addr
579