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