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