diff options
Diffstat (limited to 'src/gallium/drivers/r300/r300_texture.c')
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.c | 195 |
1 files changed, 114 insertions, 81 deletions
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 5a013e2a25..6206570fca 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -21,30 +21,28 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "pipe/p_screen.h" - -#include "util/u_format.h" -#include "util/u_format_s3tc.h" -#include "util/u_math.h" -#include "util/u_memory.h" +/* Always include headers in the reverse order!! ~ M. */ +#include "r300_texture.h" #include "r300_context.h" #include "r300_reg.h" -#include "r300_texture.h" #include "r300_transfer.h" #include "r300_screen.h" #include "r300_winsys.h" -#define TILE_WIDTH 0 -#define TILE_HEIGHT 1 +#include "util/u_format.h" +#include "util/u_format_s3tc.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +#include "pipe/p_screen.h" -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 */ +/* XXX NO! just no! */ +#include "state_tracker/drm_driver.h" + +enum r300_dim { + DIM_WIDTH = 0, + DIM_HEIGHT = 1 }; unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, @@ -596,21 +594,21 @@ static void r300_texture_setup_fb_state(struct r300_screen* screen, /* Set framebuffer state. */ if (util_format_is_depth_or_stencil(tex->b.b.format)) { for (i = 0; i <= tex->b.b.last_level; i++) { - tex->fb_state.depthpitch[i] = + tex->fb_state.pitch[i] = tex->hwpitch[i] | R300_DEPTHMACROTILE(tex->mip_macrotile[i]) | R300_DEPTHMICROTILE(tex->microtile); } - tex->fb_state.zb_format = r300_translate_zsformat(tex->b.b.format); + tex->fb_state.format = r300_translate_zsformat(tex->b.b.format); } else { for (i = 0; i <= tex->b.b.last_level; i++) { - tex->fb_state.colorpitch[i] = + tex->fb_state.pitch[i] = tex->hwpitch[i] | r300_translate_colorformat(tex->b.b.format) | R300_COLOR_TILE(tex->mip_macrotile[i]) | R300_COLOR_MICROTILE(tex->microtile); } - tex->fb_state.us_out_fmt = r300_translate_out_fmt(tex->b.b.format); + tex->fb_state.format = r300_translate_out_fmt(tex->b.b.format); } } @@ -620,8 +618,10 @@ void r300_texture_reinterpret_format(struct pipe_screen *screen, { struct r300_screen *r300screen = r300_screen(screen); - SCREEN_DBG(r300screen, DBG_TEX, "r300: texture_reinterpret_format: %s -> %s\n", - util_format_short_name(tex->format), util_format_short_name(new_format)); + SCREEN_DBG(r300screen, DBG_TEX, + "r300: texture_reinterpret_format: %s -> %s\n", + util_format_short_name(tex->format), + util_format_short_name(new_format)); tex->format = new_format; @@ -648,36 +648,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); @@ -713,8 +742,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); @@ -743,8 +772,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. */ @@ -784,21 +813,26 @@ static void r300_setup_miptree(struct r300_screen* screen, unsigned stride, size, layer_size, nblocksy, i; boolean rv350_mode = screen->caps.is_rv350; - SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Making miptree for texture, format %s\n", - util_format_short_name(base->format)); + SCREEN_DBG(screen, DBG_TEXALLOC, + "r300: Making miptree for texture, format %s\n", + util_format_short_name(base->format)); for (i = 0; i <= base->last_level; i++) { /* 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); nblocksy = r300_texture_get_nblocksy(tex, i); layer_size = stride * nblocksy; + if (base->nr_samples) { + layer_size *= base->nr_samples; + } + if (base->target == PIPE_TEXTURE_CUBE) size = layer_size * 6; else @@ -864,8 +898,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; } } @@ -899,17 +933,14 @@ static boolean r300_texture_get_handle(struct pipe_screen* screen, { struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; struct r300_texture* tex = (struct r300_texture*)texture; - unsigned stride; if (!tex) { return FALSE; } - stride = r300_texture_get_stride(r300_screen(screen), tex, 0); - - rws->buffer_get_handle(rws, tex->buffer, stride, whandle); + whandle->stride = r300_texture_get_stride(r300_screen(screen), tex, 0); - return TRUE; + return rws->buffer_get_handle(rws, tex->buffer, whandle); } struct u_resource_vtbl r300_texture_vtbl = @@ -966,11 +997,12 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen, SCREEN_DBG(rscreen, DBG_TEX, "r300: texture_create: Macro: %s, Micro: %s, Pitch: %i, " - "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n", + "Dim: %ix%ix%i, LastLevel: %i, Size: %i, Format: %s\n", tex->macrotile ? "YES" : " NO", tex->microtile ? "YES" : " NO", tex->hwpitch[0], base->width0, base->height0, base->depth0, base->last_level, + tex->size, util_format_short_name(base->format)); tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ? R300_DOMAIN_GTT : @@ -979,16 +1011,16 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen, tex->buffer = rws->buffer_create(rws, 2048, base->bind, tex->domain, tex->size); + if (!tex->buffer) { + FREE(tex); + return NULL; + } + rws->buffer_set_tiling(rws, tex->buffer, tex->pitch[0] * util_format_get_blocksize(tex->b.b.format), tex->microtile, tex->macrotile); - if (!tex->buffer) { - FREE(tex); - return NULL; - } - return (struct pipe_resource*)tex; } @@ -1002,26 +1034,27 @@ struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, unsigned flags) { struct r300_texture* tex = r300_texture(texture); - struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface); - unsigned offset; - - offset = r300_texture_get_offset(tex, level, zslice, face); + struct r300_surface* surface = CALLOC_STRUCT(r300_surface); if (surface) { - pipe_reference_init(&surface->reference, 1); - pipe_resource_reference(&surface->texture, texture); - surface->format = texture->format; - surface->width = u_minify(texture->width0, level); - surface->height = u_minify(texture->height0, level); - surface->offset = offset; - surface->usage = flags; - surface->zslice = zslice; - surface->texture = texture; - surface->face = face; - surface->level = level; + pipe_reference_init(&surface->base.reference, 1); + pipe_resource_reference(&surface->base.texture, texture); + surface->base.format = texture->format; + surface->base.width = u_minify(texture->width0, level); + surface->base.height = u_minify(texture->height0, level); + surface->base.usage = flags; + surface->base.zslice = zslice; + surface->base.face = face; + surface->base.level = level; + + surface->buffer = tex->buffer; + surface->domain = tex->domain; + surface->offset = r300_texture_get_offset(tex, level, zslice, face); + surface->pitch = tex->fb_state.pitch[level]; + surface->format = tex->fb_state.format; } - return surface; + return &surface->base; } /* Not required to implement u_resource_vtbl, consider moving to another file: @@ -1041,7 +1074,6 @@ r300_texture_from_handle(struct pipe_screen* screen, struct r300_screen* rscreen = r300_screen(screen); struct r300_winsys_buffer *buffer; struct r300_texture* tex; - unsigned stride; boolean override_zb_flags; /* Support only 2D textures without mipmaps */ @@ -1051,7 +1083,8 @@ r300_texture_from_handle(struct pipe_screen* screen, return NULL; } - buffer = rws->buffer_from_handle(rws, screen, whandle, &stride); + /* XXX make the winsys return the stride_override, see i915_resource_texture.c:830 */ + buffer = rws->buffer_from_handle(rws, whandle->handle); if (!buffer) { return NULL; } @@ -1067,7 +1100,7 @@ r300_texture_from_handle(struct pipe_screen* screen, tex->b.b.screen = screen; tex->domain = R300_DOMAIN_VRAM; - tex->stride_override = stride; + tex->stride_override = whandle->stride; /* one ref already taken */ tex->buffer = buffer; @@ -1079,7 +1112,7 @@ r300_texture_from_handle(struct pipe_screen* screen, "Pitch: % 4i, Dim: %ix%i, Format: %s\n", tex->macrotile ? "YES" : " NO", tex->microtile ? "YES" : " NO", - stride / util_format_get_blocksize(base->format), + whandle->stride / util_format_get_blocksize(base->format), base->width0, base->height0, util_format_short_name(base->format)); |