diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2013-06-20 09:55:31 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2013-06-20 09:55:31 +0000 |
commit | 30486b0838d48fe12af965016175567b12d5c317 (patch) | |
tree | f809fafd8cde63d9638f5fa26ef533613a3f2c0e /lib/libdrm/radeon | |
parent | 79b6fc556d2585f7a852bcdd1431f6bbf8552a00 (diff) |
update to libdrm 2.4.45
ok kettenis@ mpi@, tested by ajacoutot@
Diffstat (limited to 'lib/libdrm/radeon')
-rw-r--r-- | lib/libdrm/radeon/r600_pci_ids.h | 23 | ||||
-rw-r--r-- | lib/libdrm/radeon/radeon_surface.c | 660 | ||||
-rw-r--r-- | lib/libdrm/radeon/radeon_surface.h | 32 | ||||
-rw-r--r-- | lib/libdrm/radeon/shlib_version | 4 |
4 files changed, 676 insertions, 43 deletions
diff --git a/lib/libdrm/radeon/r600_pci_ids.h b/lib/libdrm/radeon/r600_pci_ids.h index ccc3ea5c7..01c900f1a 100644 --- a/lib/libdrm/radeon/r600_pci_ids.h +++ b/lib/libdrm/radeon/r600_pci_ids.h @@ -298,6 +298,10 @@ CHIPSET(0x9907, ARUBA_9907, ARUBA) CHIPSET(0x9908, ARUBA_9908, ARUBA) CHIPSET(0x9909, ARUBA_9909, ARUBA) CHIPSET(0x990A, ARUBA_990A, ARUBA) +CHIPSET(0x990B, ARUBA_990B, ARUBA) +CHIPSET(0x990C, ARUBA_990C, ARUBA) +CHIPSET(0x990D, ARUBA_990D, ARUBA) +CHIPSET(0x990E, ARUBA_990E, ARUBA) CHIPSET(0x990F, ARUBA_990F, ARUBA) CHIPSET(0x9910, ARUBA_9910, ARUBA) CHIPSET(0x9913, ARUBA_9913, ARUBA) @@ -309,6 +313,15 @@ CHIPSET(0x9991, ARUBA_9991, ARUBA) CHIPSET(0x9992, ARUBA_9992, ARUBA) CHIPSET(0x9993, ARUBA_9993, ARUBA) CHIPSET(0x9994, ARUBA_9994, ARUBA) +CHIPSET(0x9995, ARUBA_9995, ARUBA) +CHIPSET(0x9996, ARUBA_9996, ARUBA) +CHIPSET(0x9997, ARUBA_9997, ARUBA) +CHIPSET(0x9998, ARUBA_9998, ARUBA) +CHIPSET(0x9999, ARUBA_9999, ARUBA) +CHIPSET(0x999A, ARUBA_999A, ARUBA) +CHIPSET(0x999B, ARUBA_999B, ARUBA) +CHIPSET(0x999C, ARUBA_999C, ARUBA) +CHIPSET(0x999D, ARUBA_999D, ARUBA) CHIPSET(0x99A0, ARUBA_99A0, ARUBA) CHIPSET(0x99A2, ARUBA_99A2, ARUBA) CHIPSET(0x99A4, ARUBA_99A4, ARUBA) @@ -343,6 +356,7 @@ CHIPSET(0x684C, PITCAIRN_684C, PITCAIRN) CHIPSET(0x6820, VERDE_6820, VERDE) CHIPSET(0x6821, VERDE_6821, VERDE) +CHIPSET(0x6822, VERDE_6822, VERDE) CHIPSET(0x6823, VERDE_6823, VERDE) CHIPSET(0x6824, VERDE_6824, VERDE) CHIPSET(0x6825, VERDE_6825, VERDE) @@ -350,11 +364,13 @@ CHIPSET(0x6826, VERDE_6826, VERDE) CHIPSET(0x6827, VERDE_6827, VERDE) CHIPSET(0x6828, VERDE_6828, VERDE) CHIPSET(0x6829, VERDE_6829, VERDE) +CHIPSET(0x682A, VERDE_682A, VERDE) CHIPSET(0x682B, VERDE_682B, VERDE) CHIPSET(0x682D, VERDE_682D, VERDE) CHIPSET(0x682F, VERDE_682F, VERDE) CHIPSET(0x6830, VERDE_6830, VERDE) CHIPSET(0x6831, VERDE_6831, VERDE) +CHIPSET(0x6835, VERDE_6835, VERDE) CHIPSET(0x6837, VERDE_6837, VERDE) CHIPSET(0x6838, VERDE_6838, VERDE) CHIPSET(0x6839, VERDE_6839, VERDE) @@ -375,3 +391,10 @@ CHIPSET(0x6620, OLAND_6620, OLAND) CHIPSET(0x6621, OLAND_6621, OLAND) CHIPSET(0x6623, OLAND_6623, OLAND) CHIPSET(0x6631, OLAND_6631, OLAND) + +CHIPSET(0x6660, HAINAN_6660, HAINAN) +CHIPSET(0x6663, HAINAN_6663, HAINAN) +CHIPSET(0x6664, HAINAN_6664, HAINAN) +CHIPSET(0x6665, HAINAN_6665, HAINAN) +CHIPSET(0x6667, HAINAN_6667, HAINAN) +CHIPSET(0x666F, HAINAN_666F, HAINAN) diff --git a/lib/libdrm/radeon/radeon_surface.c b/lib/libdrm/radeon/radeon_surface.c index d52f4574a..a74064c46 100644 --- a/lib/libdrm/radeon/radeon_surface.c +++ b/lib/libdrm/radeon/radeon_surface.c @@ -73,6 +73,7 @@ enum radeon_family { CHIP_PITCAIRN, CHIP_VERDE, CHIP_OLAND, + CHIP_HAINAN, CHIP_LAST, }; @@ -83,12 +84,14 @@ typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man, struct radeon_hw_info { /* apply to r6, eg */ - uint32_t group_bytes; - uint32_t num_banks; - uint32_t num_pipes; + uint32_t group_bytes; + uint32_t num_banks; + uint32_t num_pipes; /* apply to eg */ - uint32_t row_size; - unsigned allow_2d; + uint32_t row_size; + unsigned allow_2d; + /* apply to si */ + uint32_t tile_mode_array[32]; }; struct radeon_surface_manager { @@ -156,7 +159,8 @@ static void surf_minify(struct radeon_surface *surf, surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w; surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h; surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d; - if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) { + if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D && + !(surf->flags & RADEON_SURF_FMASK)) { if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) { surflevel->mode = RADEON_SURF_MODE_1D; return; @@ -562,7 +566,8 @@ static void eg_surf_minify(struct radeon_surface *surf, surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w; surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h; surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d; - if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) { + if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D && + !(surf->flags & RADEON_SURF_FMASK)) { if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) { surflevel->mode = RADEON_SURF_MODE_1D; return; @@ -1000,12 +1005,403 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man, /* =========================================================================== * Southern Islands family */ +#define SI__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f) +#define SI__PIPE_CONFIG__ADDR_SURF_P2 0 +#define SI__PIPE_CONFIG__ADDR_SURF_P4_8x16 4 +#define SI__PIPE_CONFIG__ADDR_SURF_P4_16x16 5 +#define SI__PIPE_CONFIG__ADDR_SURF_P4_16x32 6 +#define SI__PIPE_CONFIG__ADDR_SURF_P4_32x32 7 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13 +#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14 +#define SI__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7) +#define SI__TILE_SPLIT__64B 0 +#define SI__TILE_SPLIT__128B 1 +#define SI__TILE_SPLIT__256B 2 +#define SI__TILE_SPLIT__512B 3 +#define SI__TILE_SPLIT__1024B 4 +#define SI__TILE_SPLIT__2048B 5 +#define SI__TILE_SPLIT__4096B 6 +#define SI__GB_TILE_MODE__BANK_WIDTH(x) (((x) >> 14) & 0x3) +#define SI__BANK_WIDTH__1 0 +#define SI__BANK_WIDTH__2 1 +#define SI__BANK_WIDTH__4 2 +#define SI__BANK_WIDTH__8 3 +#define SI__GB_TILE_MODE__BANK_HEIGHT(x) (((x) >> 16) & 0x3) +#define SI__BANK_HEIGHT__1 0 +#define SI__BANK_HEIGHT__2 1 +#define SI__BANK_HEIGHT__4 2 +#define SI__BANK_HEIGHT__8 3 +#define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 18) & 0x3) +#define SI__MACRO_TILE_ASPECT__1 0 +#define SI__MACRO_TILE_ASPECT__2 1 +#define SI__MACRO_TILE_ASPECT__4 2 +#define SI__MACRO_TILE_ASPECT__8 3 +#define SI__GB_TILE_MODE__NUM_BANKS(x) (((x) >> 20) & 0x3) +#define SI__NUM_BANKS__2_BANK 0 +#define SI__NUM_BANKS__4_BANK 1 +#define SI__NUM_BANKS__8_BANK 2 +#define SI__NUM_BANKS__16_BANK 3 + + +static void si_gb_tile_mode(uint32_t gb_tile_mode, + unsigned *num_pipes, + unsigned *num_banks, + uint32_t *macro_tile_aspect, + uint32_t *bank_w, + uint32_t *bank_h, + uint32_t *tile_split) +{ + if (num_pipes) { + switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) { + case SI__PIPE_CONFIG__ADDR_SURF_P2: + default: + *num_pipes = 2; + break; + case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16: + case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16: + case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32: + case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32: + *num_pipes = 4; + break; + case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16: + case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16: + case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16: + case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16: + case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16: + case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32: + case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32: + *num_pipes = 8; + break; + } + } + if (num_banks) { + switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) { + default: + case SI__NUM_BANKS__2_BANK: + *num_banks = 2; + break; + case SI__NUM_BANKS__4_BANK: + *num_banks = 4; + break; + case SI__NUM_BANKS__8_BANK: + *num_banks = 8; + break; + case SI__NUM_BANKS__16_BANK: + *num_banks = 16; + break; + } + } + if (macro_tile_aspect) { + switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) { + default: + case SI__MACRO_TILE_ASPECT__1: + *macro_tile_aspect = 1; + break; + case SI__MACRO_TILE_ASPECT__2: + *macro_tile_aspect = 2; + break; + case SI__MACRO_TILE_ASPECT__4: + *macro_tile_aspect = 4; + break; + case SI__MACRO_TILE_ASPECT__8: + *macro_tile_aspect = 8; + break; + } + } + if (bank_w) { + switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) { + default: + case SI__BANK_WIDTH__1: + *bank_w = 1; + break; + case SI__BANK_WIDTH__2: + *bank_w = 2; + break; + case SI__BANK_WIDTH__4: + *bank_w = 4; + break; + case SI__BANK_WIDTH__8: + *bank_w = 8; + break; + } + } + if (bank_h) { + switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) { + default: + case SI__BANK_HEIGHT__1: + *bank_h = 1; + break; + case SI__BANK_HEIGHT__2: + *bank_h = 2; + break; + case SI__BANK_HEIGHT__4: + *bank_h = 4; + break; + case SI__BANK_HEIGHT__8: + *bank_h = 8; + break; + } + } + if (tile_split) { + switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) { + default: + case SI__TILE_SPLIT__64B: + *tile_split = 64; + break; + case SI__TILE_SPLIT__128B: + *tile_split = 128; + break; + case SI__TILE_SPLIT__256B: + *tile_split = 256; + break; + case SI__TILE_SPLIT__512B: + *tile_split = 512; + break; + case SI__TILE_SPLIT__1024B: + *tile_split = 1024; + break; + case SI__TILE_SPLIT__2048B: + *tile_split = 2048; + break; + case SI__TILE_SPLIT__4096B: + *tile_split = 4096; + break; + } + } +} + +static int si_init_hw_info(struct radeon_surface_manager *surf_man) +{ + uint32_t tiling_config; + drmVersionPtr version; + int r; + + r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG, + &tiling_config); + if (r) { + return r; + } + + surf_man->hw_info.allow_2d = 0; + version = drmGetVersion(surf_man->fd); + if (version && version->version_minor >= 33) { + if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) { + surf_man->hw_info.allow_2d = 1; + } + } + drmFreeVersion(version); + + switch (tiling_config & 0xf) { + case 0: + surf_man->hw_info.num_pipes = 1; + break; + case 1: + surf_man->hw_info.num_pipes = 2; + break; + case 2: + surf_man->hw_info.num_pipes = 4; + break; + case 3: + surf_man->hw_info.num_pipes = 8; + break; + default: + surf_man->hw_info.num_pipes = 8; + surf_man->hw_info.allow_2d = 0; + break; + } + + switch ((tiling_config & 0xf0) >> 4) { + case 0: + surf_man->hw_info.num_banks = 4; + break; + case 1: + surf_man->hw_info.num_banks = 8; + break; + case 2: + surf_man->hw_info.num_banks = 16; + break; + default: + surf_man->hw_info.num_banks = 8; + surf_man->hw_info.allow_2d = 0; + break; + } + + switch ((tiling_config & 0xf00) >> 8) { + case 0: + surf_man->hw_info.group_bytes = 256; + break; + case 1: + surf_man->hw_info.group_bytes = 512; + break; + default: + surf_man->hw_info.group_bytes = 256; + surf_man->hw_info.allow_2d = 0; + break; + } + + switch ((tiling_config & 0xf000) >> 12) { + case 0: + surf_man->hw_info.row_size = 1024; + break; + case 1: + surf_man->hw_info.row_size = 2048; + break; + case 2: + surf_man->hw_info.row_size = 4096; + break; + default: + surf_man->hw_info.row_size = 4096; + surf_man->hw_info.allow_2d = 0; + break; + } + return 0; +} + +static int si_surface_sanity(struct radeon_surface_manager *surf_man, + struct radeon_surface *surf, + unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode) +{ + uint32_t gb_tile_mode; + + /* check surface dimension */ + if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) { + return -EINVAL; + } + + /* check mipmap last_level */ + if (surf->last_level > 15) { + return -EINVAL; + } + + /* force 1d on kernel that can't do 2d */ + if (mode > RADEON_SURF_MODE_1D && + (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) { + if (surf->nsamples > 1) { + fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__); + return -EFAULT; + } + mode = RADEON_SURF_MODE_1D; + surf->flags = RADEON_SURF_CLR(surf->flags, MODE); + surf->flags |= RADEON_SURF_SET(mode, MODE); + } + + if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) { + return -EINVAL; + } + + if (!surf->tile_split) { + /* default value */ + surf->mtilea = 1; + surf->bankw = 1; + surf->bankw = 1; + surf->tile_split = 64; + surf->stencil_tile_split = 64; + } + + switch (mode) { + case RADEON_SURF_MODE_2D: + if (surf->flags & RADEON_SURF_SBUFFER) { + switch (surf->nsamples) { + case 1: + *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D; + break; + case 2: + *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA; + break; + case 4: + *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA; + break; + case 8: + *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA; + break; + default: + return -EINVAL; + } + /* retrieve tiling mode value */ + gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode]; + si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split); + } + if (surf->flags & RADEON_SURF_ZBUFFER) { + switch (surf->nsamples) { + case 1: + *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D; + break; + case 2: + *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA; + break; + case 4: + *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA; + break; + case 8: + *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA; + break; + default: + return -EINVAL; + } + } else if (surf->flags & RADEON_SURF_SCANOUT) { + switch (surf->bpe) { + case 2: + *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP; + break; + case 4: + *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP; + break; + default: + return -EINVAL; + } + } else { + switch (surf->bpe) { + case 1: + *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP; + break; + case 2: + *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP; + break; + case 4: + *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP; + break; + case 8: + case 16: + *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP; + break; + default: + return -EINVAL; + } + } + /* retrieve tiling mode value */ + gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode]; + si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split); + break; + case RADEON_SURF_MODE_1D: + if (surf->flags & RADEON_SURF_SBUFFER) { + *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D; + } + if (surf->flags & RADEON_SURF_ZBUFFER) { + *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D; + } else if (surf->flags & RADEON_SURF_SCANOUT) { + *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; + } else { + *tile_mode = SI_TILE_MODE_COLOR_1D; + } + break; + case RADEON_SURF_MODE_LINEAR_ALIGNED: + default: + *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED; + } + + return 0; +} static void si_surf_minify(struct radeon_surface *surf, - struct radeon_surface_level *surflevel, - unsigned bpe, unsigned level, - uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align, - unsigned offset) + struct radeon_surface_level *surflevel, + unsigned bpe, unsigned level, + uint32_t xalign, uint32_t yalign, uint32_t zalign, + uint32_t slice_align, unsigned offset) { surflevel->npix_x = mip_minify(surf->npix_x, level); surflevel->npix_y = mip_minify(surf->npix_y, level); @@ -1043,8 +1439,53 @@ static void si_surf_minify(struct radeon_surface *surf, surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size; } +static void si_surf_minify_2d(struct radeon_surface *surf, + struct radeon_surface_level *surflevel, + unsigned bpe, unsigned level, unsigned slice_pt, + uint32_t xalign, uint32_t yalign, uint32_t zalign, + unsigned mtileb, unsigned offset) +{ + unsigned mtile_pr, mtile_ps; + + surflevel->npix_x = mip_minify(surf->npix_x, level); + surflevel->npix_y = mip_minify(surf->npix_y, level); + surflevel->npix_z = mip_minify(surf->npix_z, level); + + if (level == 0 && surf->last_level > 0) { + surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w; + surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h; + surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d; + } else { + surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w; + surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h; + surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d; + } + + if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D && + !(surf->flags & RADEON_SURF_FMASK)) { + if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) { + surflevel->mode = RADEON_SURF_MODE_1D; + return; + } + } + surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign); + surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign); + surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign); + + /* macro tile per row */ + mtile_pr = surflevel->nblk_x / xalign; + /* macro tile per slice */ + mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign; + surflevel->offset = offset; + surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt; + surflevel->slice_size = mtile_ps * mtileb * slice_pt; + + surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size; +} + static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man, struct radeon_surface *surf, + unsigned tile_mode, uint64_t offset, unsigned start_level) { uint32_t xalign, yalign, zalign, slice_align; @@ -1062,13 +1503,15 @@ static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_ma /* build mipmap tree */ for (i = start_level; i <= surf->last_level; i++) { surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED; - si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, - zalign, slice_align, offset); + si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset); /* level0 and first mipmap need to have alignment */ offset = surf->bo_size; if ((i == 0)) { offset = ALIGN(offset, surf->bo_alignment); } + if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { + surf->tiling_index[i] = tile_mode; + } } return 0; } @@ -1076,7 +1519,7 @@ static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_ma static int si_surface_init_1d(struct radeon_surface_manager *surf_man, struct radeon_surface *surf, struct radeon_surface_level *level, - unsigned bpe, + unsigned bpe, unsigned tile_mode, uint64_t offset, unsigned start_level) { uint32_t xalign, yalign, zalign, slice_align; @@ -1092,11 +1535,10 @@ static int si_surface_init_1d(struct radeon_surface_manager *surf_man, } if (!start_level) { - unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes); - surf->bo_alignment = MAX2(surf->bo_alignment, alignment); + surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes); if (offset) { - offset = ALIGN(offset, alignment); + offset = ALIGN(offset, surf->bo_alignment); } } @@ -1109,28 +1551,140 @@ static int si_surface_init_1d(struct radeon_surface_manager *surf_man, if ((i == 0)) { offset = ALIGN(offset, surf->bo_alignment); } + if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { + if (surf->level == level) { + surf->tiling_index[i] = tile_mode; + /* it's ok because stencil is done after */ + surf->stencil_tiling_index[i] = tile_mode; + } else { + surf->stencil_tiling_index[i] = tile_mode; + } + } } return 0; } static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man, - struct radeon_surface *surf) + struct radeon_surface *surf, + unsigned tile_mode, unsigned stencil_tile_mode) { - unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER; - int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags; - /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */ - struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL]; - struct radeon_surface_level *stencil_level = - (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp; + int r; - r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0); - if (r) + r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0); + if (r) { return r; + } - if (is_depth_stencil) { - r = si_surface_init_1d(surf_man, surf, stencil_level, 1, - surf->bo_size, 0); - surf->stencil_offset = stencil_level[0].offset; + if (surf->flags & RADEON_SURF_SBUFFER) { + r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0); + surf->stencil_offset = surf->stencil_level[0].offset; + } + return r; +} + +static int si_surface_init_2d(struct radeon_surface_manager *surf_man, + struct radeon_surface *surf, + struct radeon_surface_level *level, + unsigned bpe, unsigned tile_mode, + unsigned num_pipes, unsigned num_banks, + unsigned tile_split, + uint64_t offset, + unsigned start_level) +{ + unsigned tilew, tileh, tileb; + unsigned mtilew, mtileh, mtileb; + unsigned slice_pt; + unsigned i; + + /* compute tile values */ + tilew = 8; + tileh = 8; + tileb = tilew * tileh * bpe * surf->nsamples; + /* slices per tile */ + slice_pt = 1; + if (tileb > tile_split) { + slice_pt = tileb / tile_split; + } + tileb = tileb / slice_pt; + + /* macro tile width & height */ + mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea; + mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea; + + /* macro tile bytes */ + mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb; + + if (!start_level) { + unsigned alignment = MAX2(256, mtileb); + surf->bo_alignment = MAX2(surf->bo_alignment, alignment); + + if (offset) { + offset = ALIGN(offset, alignment); + } + } + + /* build mipmap tree */ + for (i = start_level; i <= surf->last_level; i++) { + level[i].mode = RADEON_SURF_MODE_2D; + si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, offset); + if (level[i].mode == RADEON_SURF_MODE_1D) { + switch (tile_mode) { + case SI_TILE_MODE_COLOR_2D_8BPP: + case SI_TILE_MODE_COLOR_2D_16BPP: + case SI_TILE_MODE_COLOR_2D_32BPP: + case SI_TILE_MODE_COLOR_2D_64BPP: + tile_mode = SI_TILE_MODE_COLOR_1D; + break; + case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP: + case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP: + tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; + break; + case SI_TILE_MODE_DEPTH_STENCIL_2D: + tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D; + break; + default: + return -EINVAL; + } + return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i); + } + /* level0 and first mipmap need to have alignment */ + offset = surf->bo_size; + if ((i == 0)) { + offset = ALIGN(offset, surf->bo_alignment); + } + if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { + if (surf->level == level) { + surf->tiling_index[i] = tile_mode; + /* it's ok because stencil is done after */ + surf->stencil_tiling_index[i] = tile_mode; + } else { + surf->stencil_tiling_index[i] = tile_mode; + } + } + } + return 0; +} + +static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man, + struct radeon_surface *surf, + unsigned tile_mode, unsigned stencil_tile_mode) +{ + unsigned num_pipes, num_banks; + uint32_t gb_tile_mode; + int r; + + /* retrieve tiling mode value */ + gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode]; + si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL); + + r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0); + if (r) { + return r; + } + + if (surf->flags & RADEON_SURF_SBUFFER) { + r = si_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, num_pipes, num_banks, surf->stencil_tile_split, surf->bo_size, 0); + surf->stencil_offset = surf->stencil_level[0].offset; } return r; } @@ -1138,7 +1692,7 @@ static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man, static int si_surface_init(struct radeon_surface_manager *surf_man, struct radeon_surface *surf) { - unsigned mode; + unsigned mode, tile_mode, stencil_tile_mode; int r; /* MSAA surfaces support the 2D mode only. */ @@ -1164,7 +1718,7 @@ static int si_surface_init(struct radeon_surface_manager *surf_man, } } - r = eg_surface_sanity(surf_man, surf, mode); + r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode); if (r) { return r; } @@ -1178,13 +1732,13 @@ static int si_surface_init(struct radeon_surface_manager *surf_man, r = r6_surface_init_linear(surf_man, surf, 0, 0); break; case RADEON_SURF_MODE_LINEAR_ALIGNED: - r = si_surface_init_linear_aligned(surf_man, surf, 0, 0); + r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0); break; case RADEON_SURF_MODE_1D: - r = si_surface_init_1d_miptrees(surf_man, surf); + r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode); break; case RADEON_SURF_MODE_2D: - r = eg_surface_init_2d_miptrees(surf_man, surf); + r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode); break; default: return -EINVAL; @@ -1192,6 +1746,28 @@ static int si_surface_init(struct radeon_surface_manager *surf_man, return r; } +/* + * depending on surface + */ +static int si_surface_best(struct radeon_surface_manager *surf_man, + struct radeon_surface *surf) +{ + unsigned mode, tile_mode, stencil_tile_mode; + + /* tiling mode */ + mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; + + if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) && + !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) { + /* depth/stencil force 1d tiling for old mesa */ + surf->flags = RADEON_SURF_CLR(surf->flags, MODE); + surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); + } + + return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode); +} + + /* =========================================================================== * public API */ @@ -1217,16 +1793,18 @@ struct radeon_surface_manager *radeon_surface_manager_new(int fd) } surf_man->surface_init = &r6_surface_init; surf_man->surface_best = &r6_surface_best; - } else { + } else if (surf_man->family <= CHIP_ARUBA) { if (eg_init_hw_info(surf_man)) { goto out_err; } - if (surf_man->family <= CHIP_ARUBA) { - surf_man->surface_init = &eg_surface_init; - } else { - surf_man->surface_init = &si_surface_init; - } + surf_man->surface_init = &eg_surface_init; surf_man->surface_best = &eg_surface_best; + } else { + if (si_init_hw_info(surf_man)) { + goto out_err; + } + surf_man->surface_init = &si_surface_init; + surf_man->surface_best = &si_surface_best; } return surf_man; diff --git a/lib/libdrm/radeon/radeon_surface.h b/lib/libdrm/radeon/radeon_surface.h index ed4b99412..bbed56f88 100644 --- a/lib/libdrm/radeon/radeon_surface.h +++ b/lib/libdrm/radeon/radeon_surface.h @@ -55,6 +55,8 @@ #define RADEON_SURF_ZBUFFER (1 << 17) #define RADEON_SURF_SBUFFER (1 << 18) #define RADEON_SURF_HAS_SBUFFER_MIPTREE (1 << 19) +#define RADEON_SURF_HAS_TILE_MODE_INDEX (1 << 20) +#define RADEON_SURF_FMASK (1 << 21) #define RADEON_SURF_GET(v, field) (((v) >> RADEON_SURF_ ## field ## _SHIFT) & RADEON_SURF_ ## field ## _MASK) #define RADEON_SURF_SET(v, field) (((v) & RADEON_SURF_ ## field ## _MASK) << RADEON_SURF_ ## field ## _SHIFT) @@ -76,6 +78,34 @@ struct radeon_surface_level { uint32_t mode; }; +enum si_tiling_mode { + SI_TILING_AUTO = 0, + + SI_TILING_COLOR_1D, + SI_TILING_COLOR_1D_SCANOUT, + SI_TILING_COLOR_2D_8BPP, + SI_TILING_COLOR_2D_16BPP, + SI_TILING_COLOR_2D_32BPP, + SI_TILING_COLOR_2D_64BPP, + SI_TILING_COLOR_2D_SCANOUT_16BPP, + SI_TILING_COLOR_2D_SCANOUT_32BPP, + SI_TILING_COLOR_LINEAR, + + SI_TILING_STENCIL_1D, + SI_TILING_STENCIL_2D, + SI_TILING_STENCIL_2D_2AA, + SI_TILING_STENCIL_2D_4AA, + SI_TILING_STENCIL_2D_8AA, + + SI_TILING_DEPTH_1D, + SI_TILING_DEPTH_2D, + SI_TILING_DEPTH_2D_2AA, + SI_TILING_DEPTH_2D_4AA, + SI_TILING_DEPTH_2D_8AA, + + SI_TILING_LAST_MODE, +}; + struct radeon_surface { uint32_t npix_x; uint32_t npix_y; @@ -104,6 +134,8 @@ struct radeon_surface { uint64_t stencil_offset; struct radeon_surface_level level[RADEON_SURF_MAX_LEVEL]; struct radeon_surface_level stencil_level[RADEON_SURF_MAX_LEVEL]; + uint32_t tiling_index[RADEON_SURF_MAX_LEVEL]; + uint32_t stencil_tiling_index[RADEON_SURF_MAX_LEVEL]; }; struct radeon_surface_manager *radeon_surface_manager_new(int fd); diff --git a/lib/libdrm/radeon/shlib_version b/lib/libdrm/radeon/shlib_version index c8860078e..b52599a16 100644 --- a/lib/libdrm/radeon/shlib_version +++ b/lib/libdrm/radeon/shlib_version @@ -1,2 +1,2 @@ -major=1 -minor=2 +major=2 +minor=0 |