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