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