aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichel Dänzer2012-08-31 12:29:33 -0500
committerMichel Dänzer2012-09-05 11:47:49 -0500
commit8572444fd0cda3e7b9557c09d2d0f7a9e049a2e7 (patch)
tree8be4dc6ae43b3e8e3c5a5d3a3fef9a9ff0d7ac3f /radeon/radeon_surface.c
parent92fd0ce4f659d7b0680543e9e5b96a3c7737a5f3 (diff)
downloadexternal-libgbm-8572444fd0cda3e7b9557c09d2d0f7a9e049a2e7.tar.gz
external-libgbm-8572444fd0cda3e7b9557c09d2d0f7a9e049a2e7.tar.xz
external-libgbm-8572444fd0cda3e7b9557c09d2d0f7a9e049a2e7.zip
radeon: Fix layout of linear aligned mipmaps on SI.
Signed-off-by: Michel Dänzer <michel.daenzer@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com>
Diffstat (limited to 'radeon/radeon_surface.c')
-rw-r--r--radeon/radeon_surface.c124
1 files changed, 123 insertions, 1 deletions
diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c
index 4118a37f..593c51c6 100644
--- a/radeon/radeon_surface.c
+++ b/radeon/radeon_surface.c
@@ -952,6 +952,124 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
952 952
953 953
954/* =========================================================================== 954/* ===========================================================================
955 * Southern Islands family
956 */
957
958static void si_surf_minify_linear_aligned(struct radeon_surface *surf,
959 unsigned level,
960 uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align,
961 unsigned offset)
962{
963 surf->level[level].npix_x = mip_minify(surf->npix_x, level);
964 surf->level[level].npix_y = mip_minify(surf->npix_y, level);
965 surf->level[level].npix_z = mip_minify(surf->npix_z, level);
966 surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
967 surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
968 surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
969
970 /* XXX: Second smallest level uses larger pitch, not sure of the real reason,
971 * my best guess so far: rows evenly distributed across slice
972 */
973 xalign = MAX2(xalign, slice_align / surf->bpe / surf->level[level].npix_y);
974
975 surf->level[level].nblk_x = ALIGN(surf->level[level].nblk_x, xalign);
976 surf->level[level].nblk_y = ALIGN(surf->level[level].nblk_y, yalign);
977 surf->level[level].nblk_z = ALIGN(surf->level[level].nblk_z, zalign);
978
979 surf->level[level].offset = offset;
980 surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * surf->nsamples;
981 surf->level[level].slice_size = ALIGN(surf->level[level].pitch_bytes * surf->level[level].nblk_y, slice_align);
982
983 surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
984}
985
986static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
987 struct radeon_surface *surf,
988 uint64_t offset, unsigned start_level)
989{
990 uint32_t xalign, yalign, zalign, slice_align;
991 unsigned i;
992
993 /* compute alignment */
994 if (!start_level) {
995 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
996 }
997 xalign = MAX2(8, 64 / surf->bpe);
998 yalign = 1;
999 zalign = 1;
1000 slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
1001
1002 /* build mipmap tree */
1003 for (i = start_level; i <= surf->last_level; i++) {
1004 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
1005 si_surf_minify_linear_aligned(surf, i, xalign, yalign, zalign, slice_align, offset);
1006 /* level0 and first mipmap need to have alignment */
1007 offset = surf->bo_size;
1008 if ((i == 0)) {
1009 offset = ALIGN(offset, surf->bo_alignment);
1010 }
1011 }
1012 return 0;
1013}
1014
1015static int si_surface_init(struct radeon_surface_manager *surf_man,
1016 struct radeon_surface *surf)
1017{
1018 unsigned mode;
1019 int r;
1020
1021 /* MSAA surfaces support the 2D mode only. */
1022 if (surf->nsamples > 1) {
1023 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1024 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1025 }
1026
1027 /* tiling mode */
1028 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1029
1030 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
1031 /* zbuffer only support 1D or 2D tiled surface */
1032 switch (mode) {
1033 case RADEON_SURF_MODE_1D:
1034 case RADEON_SURF_MODE_2D:
1035 break;
1036 default:
1037 mode = RADEON_SURF_MODE_1D;
1038 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1039 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1040 break;
1041 }
1042 }
1043
1044 r = eg_surface_sanity(surf_man, surf, mode);
1045 if (r) {
1046 return r;
1047 }
1048
1049 surf->stencil_offset = 0;
1050 surf->stencil_tile_split = 0;
1051
1052 /* check tiling mode */
1053 switch (mode) {
1054 case RADEON_SURF_MODE_LINEAR:
1055 r = r6_surface_init_linear(surf_man, surf, 0, 0);
1056 break;
1057 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1058 r = si_surface_init_linear_aligned(surf_man, surf, 0, 0);
1059 break;
1060 case RADEON_SURF_MODE_1D:
1061 r = eg_surface_init_1d(surf_man, surf, 0, 0);
1062 break;
1063 case RADEON_SURF_MODE_2D:
1064 r = eg_surface_init_2d(surf_man, surf, 0, 0);
1065 break;
1066 default:
1067 return -EINVAL;
1068 }
1069 return r;
1070}
1071
1072/* ===========================================================================
955 * public API 1073 * public API
956 */ 1074 */
957struct radeon_surface_manager *radeon_surface_manager_new(int fd) 1075struct radeon_surface_manager *radeon_surface_manager_new(int fd)
@@ -980,7 +1098,11 @@ struct radeon_surface_manager *radeon_surface_manager_new(int fd)
980 if (eg_init_hw_info(surf_man)) { 1098 if (eg_init_hw_info(surf_man)) {
981 goto out_err; 1099 goto out_err;
982 } 1100 }
983 surf_man->surface_init = &eg_surface_init; 1101 if (surf_man->family <= CHIP_ARUBA) {
1102 surf_man->surface_init = &eg_surface_init;
1103 } else {
1104 surf_man->surface_init = &si_surface_init;
1105 }
984 surf_man->surface_best = &eg_surface_best; 1106 surf_man->surface_best = &eg_surface_best;
985 } 1107 }
986 1108