summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2008-10-14 10:55:38 -0600
committerBrian Paul <[email protected]>2008-10-14 12:54:30 -0600
commit0bee156d8518419befb50ba57d22fed4037797ce (patch)
tree0aafaa3dbebd083f10b27e51082a282e64486ece
parentb7609be0f1cc8d7a822a29a2ecc165cd848df2b3 (diff)
cell: now do texture twiddling in the right way, at the right time.
Also handles images smaller than 32x32 now.
-rw-r--r--src/gallium/drivers/cell/ppu/cell_pipe_state.c2
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_emit.c4
-rw-r--r--src/gallium/drivers/cell/ppu/cell_texture.c221
-rw-r--r--src/gallium/drivers/cell/ppu/cell_texture.h4
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
@@ -62,10 +62,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);