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