From 0bee156d8518419befb50ba57d22fed4037797ce Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 14 Oct 2008 10:55:38 -0600 Subject: [PATCH] cell: now do texture twiddling in the right way, at the right time. Also handles images smaller than 32x32 now. --- .../drivers/cell/ppu/cell_pipe_state.c | 2 - .../drivers/cell/ppu/cell_state_emit.c | 4 +- src/gallium/drivers/cell/ppu/cell_texture.c | 221 +++++++----------- src/gallium/drivers/cell/ppu/cell_texture.h | 4 - 4 files changed, 83 insertions(+), 148 deletions(-) diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c index 02721e8f385..2e3086c4fae 100644 --- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c +++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c @@ -258,8 +258,6 @@ cell_set_sampler_textures(struct pipe_context *pipe, } cell->num_textures = num; - cell_update_texture_mapping(cell); /* XXX temporary! */ - cell->dirty |= CELL_NEW_TEXTURE; } diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c index 7090b4c99f7..cae546b7002 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_emit.c +++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c @@ -222,8 +222,8 @@ cell_emit_state(struct cell_context *cell) uint level; for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) { texture->start[level] = NULL; - texture->width[level] = 1; - texture->height[level] = 1; + texture->width[level] = 0; + texture->height[level] = 0; } } } diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c index ad3344aacd1..4bd87590cbf 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.c +++ b/src/gallium/drivers/cell/ppu/cell_texture.c @@ -150,15 +150,77 @@ cell_texture_release(struct pipe_screen *screen, } -#if 0 + +/** + * Convert image from linear layout to tiled layout. 4-byte pixels. + */ +static void +swizzle_image_uint(uint w, uint h, uint tile_size, uint *dst, const uint *src) +{ + const uint tile_size2 = tile_size * tile_size; + const uint h_t = (h + tile_size - 1) / tile_size; + const uint w_t = (w + tile_size - 1) / tile_size; + + uint it, jt; /* tile counters */ + uint i, j; /* intra-tile counters */ + + /* loop over dest tiles */ + for (it = 0; it < h_t; it++) { + for (jt = 0; jt < w_t; jt++) { + /* start of dest tile: */ + uint *tdst = dst + (it * w_t + jt) * tile_size2; + /* loop over texels in the tile */ + uint tile_width = MIN2(tile_size, w); + uint tile_height = MIN2(tile_size, h); + for (i = 0; i < tile_height; i++) { + for (j = 0; j < tile_width; j++) { + const uint srci = it * tile_size + i; + const uint srcj = jt * tile_size + j; + ASSERT(srci < w); + ASSERT(srcj < h); + tdst[i * TILE_SIZE + j] = src[srci * w + srcj]; + } + } + } + } +} + + +/** + * Convert linear texture image data to tiled format for SPU usage. + */ static void -cell_texture_update(struct pipe_context *pipe, struct pipe_texture *texture, - uint face, uint levelsMask) +cell_twiddle_texture(struct pipe_screen *screen, + struct pipe_surface *surface) { - /* XXX TO DO: re-tile the texture data ... */ + struct cell_texture *texture = cell_texture(surface->texture); + const uint level = surface->level; + const uint texWidth = texture->base.width[level]; + const uint texHeight = texture->base.height[level]; + const uint bufWidth = MAX2(texWidth, TILE_SIZE); + const uint bufHeight = MAX2(texHeight, TILE_SIZE); + const uint *src = + (const uint *) pipe_buffer_map(screen, surface->buffer, + PIPE_BUFFER_USAGE_CPU_READ); + + switch (texture->base.format) { + case PIPE_FORMAT_A8R8G8B8_UNORM: + /* free old tiled data */ + if (texture->tiled_data[level]) { + align_free(texture->tiled_data[level]); + } + /* alloc new tiled data */ + texture->tiled_data[level] = align_malloc(bufWidth * bufHeight * 4, 16); + swizzle_image_uint(texWidth, texHeight, TILE_SIZE, + texture->tiled_data[level], src); + break; + default: + printf("Unsupported texture format\n"); + ; + } + pipe_buffer_unmap(screen, surface->buffer); } -#endif static struct pipe_surface * @@ -207,129 +269,12 @@ cell_get_tex_surface(struct pipe_screen *screen, } - -/** - * Copy tile data from linear layout to tiled layout. - * XXX this should be rolled into the future surface-creation code. - * XXX also need "untile" code... - */ -static void -tile_copy_data(uint w, uint h, uint tile_size, uint *dst, const uint *src) -{ - const uint tile_size2 = tile_size * tile_size; - const uint h_t = h / tile_size, w_t = w / tile_size; - - uint it, jt; /* tile counters */ - uint i, j; /* intra-tile counters */ - - /* loop over dest tiles */ - for (it = 0; it < h_t; it++) { - for (jt = 0; jt < w_t; jt++) { - /* start of dest tile: */ - uint *tdst = dst + (it * w_t + jt) * tile_size2; - /* loop over texels in the tile */ - for (i = 0; i < tile_size; i++) { - for (j = 0; j < tile_size; j++) { - const uint srci = it * tile_size + i; - const uint srcj = jt * tile_size + j; - *tdst++ = src[srci * w + srcj]; - } - } - } - } -} - - - -/** - * Convert linear texture image data to tiled format for SPU usage. - * XXX recast this in terms of pipe_surfaces (aka texture views). - */ -static void -cell_tile_texture(struct cell_context *cell, - struct cell_texture *texture) -{ - struct pipe_screen *screen = cell->pipe.screen; - uint face = 0, level, zslice = 0; - const uint *src; - - for (level = 0; level <= texture->base.last_level; level++) { - if (!texture->tiled_data[level]) { - struct pipe_surface *surf; - - const uint w = texture->base.width[level], h = texture->base.height[level]; - - if (w < 32 || h < 32) - continue; - /* temporary restrictions: */ - assert(w >= TILE_SIZE); - assert(h >= TILE_SIZE); - assert(w % TILE_SIZE == 0); - assert(h % TILE_SIZE == 0); - - surf = screen->get_tex_surface(screen, &texture->base, face, - level, zslice, - PIPE_BUFFER_USAGE_CPU_WRITE); - ASSERT(surf); - - src = (const uint *) pipe_surface_map(surf, - PIPE_BUFFER_USAGE_CPU_WRITE); - - if (texture->tiled_data[level]) { - align_free(texture->tiled_data[level]); - } - texture->tiled_data[level] = align_malloc(w * h * 4, 16); - - tile_copy_data(w, h, TILE_SIZE, texture->tiled_data[level], src); - - pipe_surface_unmap(surf); - - pipe_surface_reference(&surf, NULL); - } - } -} - - -/** XXX temporary hack */ -void -cell_update_texture_mapping(struct cell_context *cell) -{ -#if 0 - uint face = 0, level = 0, zslice = 0; -#endif - uint i; - - for (i = 0; i < CELL_MAX_SAMPLERS; i++) { - if (cell->texture[i]) - cell_tile_texture(cell, cell->texture[i]); - } - -#if 0 - if (cell->tex_surf && cell->tex_map) { - pipe_surface_unmap(cell->tex_surf); - cell->tex_map = NULL; - } - - /* XXX free old surface */ - - cell->tex_surf = cell_get_tex_surface(&cell->pipe, - &cell->texture[0]->base, - face, level, zslice); - - cell->tex_map = pipe_surface_map(cell->tex_surf); -#endif -} - - static void cell_tex_surface_release(struct pipe_screen *screen, struct pipe_surface **s) { - /* Effectively do the texture_update work here - if texture images - * needed post-processing to put them into hardware layout, this is - * where it would happen. For softpipe, nothing to do. - */ - assert ((*s)->texture); + /* XXX if done rendering to teximage, re-tile */ + pipe_texture_reference(&(*s)->texture, NULL); screen->winsys->surface_release(screen->winsys, s); @@ -351,22 +296,8 @@ cell_surface_map(struct pipe_screen *screen, map = pipe_buffer_map( screen, surface->buffer, flags ); if (map == NULL) return NULL; - - /* May want to different things here depending on read/write nature - * of the map: - */ - if (surface->texture && - (flags & PIPE_BUFFER_USAGE_CPU_WRITE)) - { - /* Do something to notify sharing contexts of a texture change. - * In softpipe, that would mean flushing the texture cache. - */ -#if 0 - cell_screen(screen)->timestamp++; -#endif - } - - return (void *) (map + surface->offset); + else + return (void *) (map + surface->offset); } @@ -374,6 +305,16 @@ static void cell_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface) { + struct cell_texture *ct = cell_texture(surface->texture); + + assert(ct); + + if ((ct->base.tex_usage & PIPE_TEXTURE_USAGE_SAMPLER) && + (surface->usage & PIPE_BUFFER_USAGE_CPU_WRITE)) { + /* convert from linear to tiled layout */ + cell_twiddle_texture(screen, surface); + } + pipe_buffer_unmap( screen, surface->buffer ); } diff --git a/src/gallium/drivers/cell/ppu/cell_texture.h b/src/gallium/drivers/cell/ppu/cell_texture.h index 46475097433..a0757091b07 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.h +++ b/src/gallium/drivers/cell/ppu/cell_texture.h @@ -61,10 +61,6 @@ cell_texture(struct pipe_texture *pt) -extern void -cell_update_texture_mapping(struct cell_context *cell); - - extern void cell_init_screen_texture_funcs(struct pipe_screen *screen); -- 2.30.2