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