radeon: implement 2D tiling for CIK

Bug fixes and simplification by Marek.
We have to use the tile index of 0 for non-MSAA depth-stencil after all.

Signed-off-by: Marek Olšák <marek.olsak@amd.com>
Reviewed-and-Tested-by: Michel Dänzer <michel.daenzer@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
main
Marek Olšák 2013-11-22 23:31:13 +01:00
parent ce8af45425
commit 67d92404d6
3 changed files with 624 additions and 13 deletions

View File

@ -979,6 +979,10 @@ struct drm_radeon_cs {
#define RADEON_INFO_RING_WORKING 0x15 #define RADEON_INFO_RING_WORKING 0x15
/* SI tile mode array */ /* SI tile mode array */
#define RADEON_INFO_SI_TILE_MODE_ARRAY 0x16 #define RADEON_INFO_SI_TILE_MODE_ARRAY 0x16
/* query if CP DMA is supported on the compute ring */
#define RADEON_INFO_SI_CP_DMA_COMPUTE 0x17
/* CIK macrotile mode array */
#define RADEON_INFO_CIK_MACROTILE_MODE_ARRAY 0x18
struct drm_radeon_info { struct drm_radeon_info {
uint32_t request; uint32_t request;
@ -1004,6 +1008,13 @@ struct drm_radeon_info {
#define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA 3 #define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA 3
#define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA 2 #define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA 2
#define CIK_TILE_MODE_COLOR_2D 14
#define CIK_TILE_MODE_COLOR_2D_SCANOUT 10
#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64 0
#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128 1
#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256 2
#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512 3
#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE 4
#define CIK_TILE_MODE_DEPTH_STENCIL_1D 5 #define CIK_TILE_MODE_DEPTH_STENCIL_1D 5
#endif #endif

View File

@ -26,6 +26,8 @@
* Authors: * Authors:
* Jérôme Glisse <jglisse@redhat.com> * Jérôme Glisse <jglisse@redhat.com>
*/ */
#include <stdbool.h>
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -96,6 +98,8 @@ struct radeon_hw_info {
unsigned allow_2d; unsigned allow_2d;
/* apply to si */ /* apply to si */
uint32_t tile_mode_array[32]; uint32_t tile_mode_array[32];
/* apply to cik */
uint32_t macrotile_mode_array[16];
}; };
struct radeon_surface_manager { struct radeon_surface_manager {
@ -1383,16 +1387,10 @@ static int si_surface_sanity(struct radeon_surface_manager *surf_man,
break; break;
case RADEON_SURF_MODE_1D: case RADEON_SURF_MODE_1D:
if (surf->flags & RADEON_SURF_SBUFFER) { if (surf->flags & RADEON_SURF_SBUFFER) {
if (surf_man->family >= CHIP_BONAIRE) *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
*stencil_tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
else
*stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
} }
if (surf->flags & RADEON_SURF_ZBUFFER) { if (surf->flags & RADEON_SURF_ZBUFFER) {
if (surf_man->family >= CHIP_BONAIRE) *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
*tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
else
*tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
} else if (surf->flags & RADEON_SURF_SCANOUT) { } else if (surf->flags & RADEON_SURF_SCANOUT) {
*tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
} else { } else {
@ -1660,10 +1658,7 @@ static int si_surface_init_2d(struct radeon_surface_manager *surf_man,
tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
break; break;
case SI_TILE_MODE_DEPTH_STENCIL_2D: case SI_TILE_MODE_DEPTH_STENCIL_2D:
if (surf_man->family >= CHIP_BONAIRE) tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
else
tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -1791,6 +1786,604 @@ static int si_surface_best(struct radeon_surface_manager *surf_man,
} }
/* ===========================================================================
* Sea Islands family
*/
#define CIK__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
#define CIK__PIPE_CONFIG__ADDR_SURF_P2 0
#define CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
#define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
#define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
#define CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
#define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
#define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
#define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
#define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
#define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
#define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
#define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
#define CIK__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
#define CIK__TILE_SPLIT__64B 0
#define CIK__TILE_SPLIT__128B 1
#define CIK__TILE_SPLIT__256B 2
#define CIK__TILE_SPLIT__512B 3
#define CIK__TILE_SPLIT__1024B 4
#define CIK__TILE_SPLIT__2048B 5
#define CIK__TILE_SPLIT__4096B 6
#define CIK__GB_TILE_MODE__SAMPLE_SPLIT(x) (((x) >> 25) & 0x3)
#define CIK__SAMPLE_SPLIT__1 0
#define CIK__SAMPLE_SPLIT__2 1
#define CIK__SAMPLE_SPLIT__4 2
#define CIK__SAMPLE_SPLIT__8 3
#define CIK__GB_MACROTILE_MODE__BANK_WIDTH(x) ((x) & 0x3)
#define CIK__BANK_WIDTH__1 0
#define CIK__BANK_WIDTH__2 1
#define CIK__BANK_WIDTH__4 2
#define CIK__BANK_WIDTH__8 3
#define CIK__GB_MACROTILE_MODE__BANK_HEIGHT(x) (((x) >> 2) & 0x3)
#define CIK__BANK_HEIGHT__1 0
#define CIK__BANK_HEIGHT__2 1
#define CIK__BANK_HEIGHT__4 2
#define CIK__BANK_HEIGHT__8 3
#define CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 4) & 0x3)
#define CIK__MACRO_TILE_ASPECT__1 0
#define CIK__MACRO_TILE_ASPECT__2 1
#define CIK__MACRO_TILE_ASPECT__4 2
#define CIK__MACRO_TILE_ASPECT__8 3
#define CIK__GB_MACROTILE_MODE__NUM_BANKS(x) (((x) >> 6) & 0x3)
#define CIK__NUM_BANKS__2_BANK 0
#define CIK__NUM_BANKS__4_BANK 1
#define CIK__NUM_BANKS__8_BANK 2
#define CIK__NUM_BANKS__16_BANK 3
static void cik_get_2d_params(struct radeon_surface_manager *surf_man,
unsigned bpe, unsigned nsamples, bool is_color,
unsigned tile_mode,
uint32_t *num_pipes,
uint32_t *tile_split_ptr,
uint32_t *num_banks,
uint32_t *macro_tile_aspect,
uint32_t *bank_w,
uint32_t *bank_h)
{
uint32_t gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
unsigned tileb_1x, tileb;
unsigned gb_macrotile_mode;
unsigned macrotile_index;
unsigned tile_split, sample_split;
if (num_pipes) {
switch (CIK__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
case CIK__PIPE_CONFIG__ADDR_SURF_P2:
default:
*num_pipes = 2;
break;
case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16:
case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16:
case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32:
case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32:
*num_pipes = 4;
break;
case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
*num_pipes = 8;
break;
}
}
switch (CIK__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
default:
case CIK__TILE_SPLIT__64B:
tile_split = 64;
break;
case CIK__TILE_SPLIT__128B:
tile_split = 128;
break;
case CIK__TILE_SPLIT__256B:
tile_split = 256;
break;
case CIK__TILE_SPLIT__512B:
tile_split = 512;
break;
case CIK__TILE_SPLIT__1024B:
tile_split = 1024;
break;
case CIK__TILE_SPLIT__2048B:
tile_split = 2048;
break;
case CIK__TILE_SPLIT__4096B:
tile_split = 4096;
break;
}
switch (CIK__GB_TILE_MODE__SAMPLE_SPLIT(gb_tile_mode)) {
default:
case CIK__SAMPLE_SPLIT__1:
sample_split = 1;
break;
case CIK__SAMPLE_SPLIT__2:
sample_split = 1;
break;
case CIK__SAMPLE_SPLIT__4:
sample_split = 4;
break;
case CIK__SAMPLE_SPLIT__8:
sample_split = 8;
break;
}
/* Adjust the tile split. */
tileb_1x = 8 * 8 * bpe;
if (is_color) {
tile_split = MAX2(256, sample_split * tileb_1x);
}
tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
/* Determine the macrotile index. */
tileb = MIN2(tile_split, nsamples * tileb_1x);
for (macrotile_index = 0; tileb > 64; macrotile_index++) {
tileb >>= 1;
}
gb_macrotile_mode = surf_man->hw_info.macrotile_mode_array[macrotile_index];
if (tile_split_ptr) {
*tile_split_ptr = tile_split;
}
if (num_banks) {
switch (CIK__GB_MACROTILE_MODE__NUM_BANKS(gb_macrotile_mode)) {
default:
case CIK__NUM_BANKS__2_BANK:
*num_banks = 2;
break;
case CIK__NUM_BANKS__4_BANK:
*num_banks = 4;
break;
case CIK__NUM_BANKS__8_BANK:
*num_banks = 8;
break;
case CIK__NUM_BANKS__16_BANK:
*num_banks = 16;
break;
}
}
if (macro_tile_aspect) {
switch (CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(gb_macrotile_mode)) {
default:
case CIK__MACRO_TILE_ASPECT__1:
*macro_tile_aspect = 1;
break;
case CIK__MACRO_TILE_ASPECT__2:
*macro_tile_aspect = 2;
break;
case CIK__MACRO_TILE_ASPECT__4:
*macro_tile_aspect = 4;
break;
case CIK__MACRO_TILE_ASPECT__8:
*macro_tile_aspect = 8;
break;
}
}
if (bank_w) {
switch (CIK__GB_MACROTILE_MODE__BANK_WIDTH(gb_macrotile_mode)) {
default:
case CIK__BANK_WIDTH__1:
*bank_w = 1;
break;
case CIK__BANK_WIDTH__2:
*bank_w = 2;
break;
case CIK__BANK_WIDTH__4:
*bank_w = 4;
break;
case CIK__BANK_WIDTH__8:
*bank_w = 8;
break;
}
}
if (bank_h) {
switch (CIK__GB_MACROTILE_MODE__BANK_HEIGHT(gb_macrotile_mode)) {
default:
case CIK__BANK_HEIGHT__1:
*bank_h = 1;
break;
case CIK__BANK_HEIGHT__2:
*bank_h = 2;
break;
case CIK__BANK_HEIGHT__4:
*bank_h = 4;
break;
case CIK__BANK_HEIGHT__8:
*bank_h = 8;
break;
}
}
}
static int cik_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 >= 35) {
if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array) &&
!radeon_get_value(surf_man->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, surf_man->hw_info.macrotile_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 cik_surface_sanity(struct radeon_surface_manager *surf_man,
struct radeon_surface *surf,
unsigned mode, unsigned *tile_mode, unsigned *stencil_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_Z_OR_SBUFFER) {
switch (surf->nsamples) {
case 1:
*tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64;
break;
case 2:
case 4:
*tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128;
break;
case 8:
*tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256;
break;
default:
return -EINVAL;
}
if (surf->flags & RADEON_SURF_SBUFFER) {
*stencil_tile_mode = *tile_mode;
cik_get_2d_params(surf_man, 1, surf->nsamples, false,
*stencil_tile_mode, NULL,
&surf->stencil_tile_split,
NULL, NULL, NULL, NULL);
}
} else if (surf->flags & RADEON_SURF_SCANOUT) {
*tile_mode = CIK_TILE_MODE_COLOR_2D_SCANOUT;
} else {
*tile_mode = CIK_TILE_MODE_COLOR_2D;
}
/* retrieve tiling mode values */
cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
!(surf->flags & RADEON_SURF_Z_OR_SBUFFER), *tile_mode,
NULL, &surf->tile_split, NULL, &surf->mtilea,
&surf->bankw, &surf->bankh);
break;
}
case RADEON_SURF_MODE_1D:
if (surf->flags & RADEON_SURF_SBUFFER) {
*stencil_tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
}
if (surf->flags & RADEON_SURF_ZBUFFER) {
*tile_mode = CIK_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 int cik_surface_init_2d(struct radeon_surface_manager *surf_man,
struct radeon_surface *surf,
struct radeon_surface_level *level,
unsigned bpe, unsigned tile_mode,
unsigned tile_split,
unsigned num_pipes, unsigned num_banks,
uint64_t offset,
unsigned start_level)
{
uint64_t aligned_offset = offset;
unsigned tilew, tileh, tileb_1x, tileb;
unsigned mtilew, mtileh, mtileb;
unsigned slice_pt;
unsigned i;
/* compute tile values */
tilew = 8;
tileh = 8;
tileb_1x = tilew * tileh * bpe;
tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
tileb = surf->nsamples * tileb_1x;
/* 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 <= 1) {
unsigned alignment = MAX2(256, mtileb);
surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
if (aligned_offset) {
aligned_offset = ALIGN(aligned_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, aligned_offset);
if (level[i].mode == RADEON_SURF_MODE_1D) {
switch (tile_mode) {
case CIK_TILE_MODE_COLOR_2D:
tile_mode = SI_TILE_MODE_COLOR_1D;
break;
case CIK_TILE_MODE_COLOR_2D_SCANOUT:
tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
break;
case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64:
case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128:
case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256:
case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512:
case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE:
tile_mode = CIK_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 */
aligned_offset = offset = surf->bo_size;
if (i == 0) {
aligned_offset = ALIGN(aligned_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 cik_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
struct radeon_surface *surf,
unsigned tile_mode, unsigned stencil_tile_mode)
{
int r;
uint32_t num_pipes, num_banks;
cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
!(surf->flags & RADEON_SURF_Z_OR_SBUFFER), tile_mode,
&num_pipes, NULL, &num_banks, NULL, NULL, NULL);
r = cik_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode,
surf->tile_split, num_pipes, num_banks, 0, 0);
if (r) {
return r;
}
if (surf->flags & RADEON_SURF_SBUFFER) {
r = cik_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode,
surf->stencil_tile_split, num_pipes, num_banks,
surf->bo_size, 0);
surf->stencil_offset = surf->stencil_level[0].offset;
}
return r;
}
static int cik_surface_init(struct radeon_surface_manager *surf_man,
struct radeon_surface *surf)
{
unsigned mode, tile_mode, stencil_tile_mode;
int r;
/* MSAA surfaces support the 2D mode only. */
if (surf->nsamples > 1) {
surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
}
/* tiling mode */
mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
/* zbuffer only support 1D or 2D tiled surface */
switch (mode) {
case RADEON_SURF_MODE_1D:
case RADEON_SURF_MODE_2D:
break;
default:
mode = RADEON_SURF_MODE_1D;
surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
break;
}
}
r = cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
if (r) {
return r;
}
surf->stencil_offset = 0;
surf->bo_alignment = 0;
/* check tiling mode */
switch (mode) {
case RADEON_SURF_MODE_LINEAR:
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, tile_mode, 0, 0);
break;
case RADEON_SURF_MODE_1D:
r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
break;
case RADEON_SURF_MODE_2D:
r = cik_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
break;
default:
return -EINVAL;
}
return r;
}
/*
* depending on surface
*/
static int cik_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 cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
}
/* =========================================================================== /* ===========================================================================
* public API * public API
*/ */
@ -1822,12 +2415,18 @@ struct radeon_surface_manager *radeon_surface_manager_new(int fd)
} }
surf_man->surface_init = &eg_surface_init; surf_man->surface_init = &eg_surface_init;
surf_man->surface_best = &eg_surface_best; surf_man->surface_best = &eg_surface_best;
} else { } else if (surf_man->family < CHIP_BONAIRE) {
if (si_init_hw_info(surf_man)) { if (si_init_hw_info(surf_man)) {
goto out_err; goto out_err;
} }
surf_man->surface_init = &si_surface_init; surf_man->surface_init = &si_surface_init;
surf_man->surface_best = &si_surface_best; surf_man->surface_best = &si_surface_best;
} else {
if (cik_init_hw_info(surf_man)) {
goto out_err;
}
surf_man->surface_init = &cik_surface_init;
surf_man->surface_best = &cik_surface_best;
} }
return surf_man; return surf_man;

View File

@ -54,6 +54,7 @@
#define RADEON_SURF_SCANOUT (1 << 16) #define RADEON_SURF_SCANOUT (1 << 16)
#define RADEON_SURF_ZBUFFER (1 << 17) #define RADEON_SURF_ZBUFFER (1 << 17)
#define RADEON_SURF_SBUFFER (1 << 18) #define RADEON_SURF_SBUFFER (1 << 18)
#define RADEON_SURF_Z_OR_SBUFFER (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)
#define RADEON_SURF_HAS_SBUFFER_MIPTREE (1 << 19) #define RADEON_SURF_HAS_SBUFFER_MIPTREE (1 << 19)
#define RADEON_SURF_HAS_TILE_MODE_INDEX (1 << 20) #define RADEON_SURF_HAS_TILE_MODE_INDEX (1 << 20)
#define RADEON_SURF_FMASK (1 << 21) #define RADEON_SURF_FMASK (1 << 21)