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