diff options
Diffstat (limited to 'src/gallium/drivers/r600/r600_pipe.c')
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.c | 123 |
1 files changed, 122 insertions, 1 deletions
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index a3fc61822e7..7c8480772d2 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -589,18 +589,140 @@ static boolean r600_fence_finish(struct pipe_screen *pscreen, return TRUE; } +static int r600_interpret_tiling(struct r600_screen *rscreen, uint32_t tiling_config) +{ + switch ((tiling_config & 0xe) >> 1) { + case 0: + rscreen->tiling_info.num_channels = 1; + break; + case 1: + rscreen->tiling_info.num_channels = 2; + break; + case 2: + rscreen->tiling_info.num_channels = 4; + break; + case 3: + rscreen->tiling_info.num_channels = 8; + break; + default: + return -EINVAL; + } + + switch ((tiling_config & 0x30) >> 4) { + case 0: + rscreen->tiling_info.num_banks = 4; + break; + case 1: + rscreen->tiling_info.num_banks = 8; + break; + default: + return -EINVAL; + + } + switch ((tiling_config & 0xc0) >> 6) { + case 0: + rscreen->tiling_info.group_bytes = 256; + break; + case 1: + rscreen->tiling_info.group_bytes = 512; + break; + default: + return -EINVAL; + } + return 0; +} + +static int evergreen_interpret_tiling(struct r600_screen *rscreen, uint32_t tiling_config) +{ + switch (tiling_config & 0xf) { + case 0: + rscreen->tiling_info.num_channels = 1; + break; + case 1: + rscreen->tiling_info.num_channels = 2; + break; + case 2: + rscreen->tiling_info.num_channels = 4; + break; + case 3: + rscreen->tiling_info.num_channels = 8; + break; + default: + return -EINVAL; + } + + switch ((tiling_config & 0xf0) >> 4) { + case 0: + rscreen->tiling_info.num_banks = 4; + break; + case 1: + rscreen->tiling_info.num_banks = 8; + break; + case 2: + rscreen->tiling_info.num_banks = 16; + break; + default: + return -EINVAL; + } + + switch ((tiling_config & 0xf00) >> 8) { + case 0: + rscreen->tiling_info.group_bytes = 256; + break; + case 1: + rscreen->tiling_info.group_bytes = 512; + break; + default: + return -EINVAL; + } + return 0; +} + +static int r600_init_tiling(struct r600_screen *rscreen) +{ + uint32_t tiling_config = rscreen->info.r600_tiling_config; + + /* set default group bytes, overridden by tiling info ioctl */ + if (r600_get_family_class(rscreen->radeon) <= R700) { + rscreen->tiling_info.group_bytes = 256; + } else { + rscreen->tiling_info.group_bytes = 512; + } + + if (!tiling_config) + return 0; + + if (r600_get_family_class(rscreen->radeon) <= R700) { + return r600_interpret_tiling(rscreen, tiling_config); + } else { + return evergreen_interpret_tiling(rscreen, tiling_config); + } +} + struct pipe_screen *r600_screen_create(struct radeon_winsys *ws) { struct r600_screen *rscreen; struct radeon *radeon = radeon_create(ws); + if (!radeon) { + return NULL; + } rscreen = CALLOC_STRUCT(r600_screen); if (rscreen == NULL) { + radeon_destroy(radeon); return NULL; } rscreen->ws = ws; rscreen->radeon = radeon; + ws->query_info(ws, &rscreen->info); + + if (r600_init_tiling(rscreen)) { + radeon_destroy(radeon); + FREE(rscreen); + return NULL; + } + rscreen->screen.winsys = (struct pipe_winsys*)ws; rscreen->screen.destroy = r600_destroy_screen; rscreen->screen.get_name = r600_get_name; @@ -621,7 +743,6 @@ struct pipe_screen *r600_screen_create(struct radeon_winsys *ws) rscreen->screen.fence_finish = r600_fence_finish; r600_init_screen_resource_functions(&rscreen->screen); - rscreen->tiling_info = r600_get_tiling_info(radeon); util_format_s3tc_init(); util_slab_create(&rscreen->pool_buffers, |