diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.c | 94 |
1 files changed, 58 insertions, 36 deletions
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index f41c5301d90..de65c61e97c 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -35,16 +35,9 @@ #include "r300_screen.h" #include "r300_winsys.h" -#define TILE_WIDTH 0 -#define TILE_HEIGHT 1 - -static const unsigned microblock_table[5][3][2] = { - /*linear tiled square-tiled */ - {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */ - {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */ - {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */ - {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */ - {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ +enum r300_dim { + DIM_WIDTH = 0, + DIM_HEIGHT = 1 }; unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, @@ -650,36 +643,65 @@ unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, } } -/** - * Return the width (dim==TILE_WIDTH) or height (dim==TILE_HEIGHT) of one tile - * of the given texture. - */ -static unsigned r300_texture_get_tile_size(struct r300_texture* tex, - int dim, boolean macrotile) +/* Returns the number of pixels that the texture should be aligned to + * in the given dimension. */ +static unsigned r300_get_pixel_alignment(struct r300_texture *tex, + enum r300_buffer_tiling macrotile, + enum r300_dim dim) { - unsigned pixsize, tile_size; - - pixsize = util_format_get_blocksize(tex->b.b.format); - tile_size = microblock_table[util_logbase2(pixsize)][tex->microtile][dim]; - - if (macrotile) { - tile_size *= 8; + static const unsigned table[2][5][3][2] = + { + { + /* Macro: linear linear linear + Micro: linear tiled square-tiled */ + {{ 32, 1}, { 8, 4}, { 0, 0}}, /* 8 bits per pixel */ + {{ 16, 1}, { 8, 2}, { 4, 4}}, /* 16 bits per pixel */ + {{ 8, 1}, { 4, 2}, { 0, 0}}, /* 32 bits per pixel */ + {{ 4, 1}, { 0, 0}, { 2, 2}}, /* 64 bits per pixel */ + {{ 2, 1}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */ + }, + { + /* Macro: tiled tiled tiled + Micro: linear tiled square-tiled */ + {{256, 8}, {64, 32}, { 0, 0}}, /* 8 bits per pixel */ + {{128, 8}, {64, 16}, {32, 32}}, /* 16 bits per pixel */ + {{ 64, 8}, {32, 16}, { 0, 0}}, /* 32 bits per pixel */ + {{ 32, 8}, { 0, 0}, {16, 16}}, /* 64 bits per pixel */ + {{ 16, 8}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */ + } + }; + static const unsigned aa_block[2] = {4, 8}; + unsigned res = 0; + unsigned pixsize = util_format_get_blocksize(tex->b.b.format); + + assert(macrotile <= R300_BUFFER_TILED); + assert(tex->microtile <= R300_BUFFER_SQUARETILED); + assert(pixsize <= 16); + assert(dim <= DIM_HEIGHT); + + if (tex->b.b.nr_samples > 1) { + /* Multisampled textures have their own alignment scheme. */ + if (pixsize == 4) + res = aa_block[dim]; + } else { + /* Standard alignment. */ + res = table[macrotile][util_logbase2(pixsize)][tex->microtile][dim]; } - assert(tile_size); - return tile_size; + assert(res); + return res; } /* Return true if macrotiling should be enabled on the miplevel. */ static boolean r300_texture_macro_switch(struct r300_texture *tex, unsigned level, boolean rv350_mode, - int dim) + enum r300_dim dim) { unsigned tile, texdim; - tile = r300_texture_get_tile_size(tex, dim, TRUE); - if (dim == TILE_WIDTH) { + tile = r300_get_pixel_alignment(tex, R300_BUFFER_TILED, dim); + if (dim == DIM_WIDTH) { texdim = u_minify(tex->b.b.width0, level); } else { texdim = u_minify(tex->b.b.height0, level); @@ -715,8 +737,8 @@ unsigned r300_texture_get_stride(struct r300_screen* screen, width = u_minify(tex->b.b.width0, level); if (util_format_is_plain(tex->b.b.format)) { - tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH, - tex->mip_macrotile[level]); + tile_width = r300_get_pixel_alignment(tex, tex->mip_macrotile[level], + DIM_WIDTH); width = align(width, tile_width); stride = util_format_get_stride(tex->b.b.format, width); @@ -745,8 +767,8 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture* tex, height = u_minify(tex->b.b.height0, level); if (util_format_is_plain(tex->b.b.format)) { - tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT, - tex->mip_macrotile[level]); + tile_height = r300_get_pixel_alignment(tex, tex->mip_macrotile[level], + DIM_HEIGHT); height = align(height, tile_height); /* This is needed for the kernel checker, unfortunately. */ @@ -794,8 +816,8 @@ static void r300_setup_miptree(struct r300_screen* screen, /* Let's see if this miplevel can be macrotiled. */ tex->mip_macrotile[i] = (tex->macrotile == R300_BUFFER_TILED && - r300_texture_macro_switch(tex, i, rv350_mode, TILE_WIDTH) && - r300_texture_macro_switch(tex, i, rv350_mode, TILE_HEIGHT)) ? + r300_texture_macro_switch(tex, i, rv350_mode, DIM_WIDTH) && + r300_texture_macro_switch(tex, i, rv350_mode, DIM_HEIGHT)) ? R300_BUFFER_TILED : R300_BUFFER_LINEAR; stride = r300_texture_get_stride(screen, tex, i); @@ -871,8 +893,8 @@ static void r300_setup_tiling(struct pipe_screen *screen, } /* Set macrotiling. */ - if (r300_texture_macro_switch(tex, 0, rv350_mode, TILE_WIDTH) && - r300_texture_macro_switch(tex, 0, rv350_mode, TILE_HEIGHT)) { + if (r300_texture_macro_switch(tex, 0, rv350_mode, DIM_WIDTH) && + r300_texture_macro_switch(tex, 0, rv350_mode, DIM_HEIGHT)) { tex->macrotile = R300_BUFFER_TILED; } } |