summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/cell/ppu
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2009-02-24 20:58:46 -0700
committerBrian Paul <brianp@vmware.com>2009-02-24 21:01:34 -0700
commit192b7f20ebbe6e5ed7d7c8d8cb25ace019723689 (patch)
treec41e31618fa4fb6440c4889050e8dde13efd0ab9 /src/gallium/drivers/cell/ppu
parentbd0370cd26e4fe9bc84afdb3d087e46b38022961 (diff)
cell: overhaul cell teximage code
Updated to use the new pipe_transfer functions, etc. Texturing is working again. Though there's some bugs in mipmap texturing but I believe those predate the pipe_transfer changes.
Diffstat (limited to 'src/gallium/drivers/cell/ppu')
-rw-r--r--src/gallium/drivers/cell/ppu/cell_context.h6
-rw-r--r--src/gallium/drivers/cell/ppu/cell_fence.c12
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_emit.c18
-rw-r--r--src/gallium/drivers/cell/ppu/cell_texture.c332
-rw-r--r--src/gallium/drivers/cell/ppu/cell_texture.h17
5 files changed, 119 insertions, 266 deletions
diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h
index ca03dc1511..5c3188e7f9 100644
--- a/src/gallium/drivers/cell/ppu/cell_context.h
+++ b/src/gallium/drivers/cell/ppu/cell_context.h
@@ -127,15 +127,9 @@ struct cell_context
struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
uint num_vertex_elements;
- struct pipe_transfer *cbuf_transfer[PIPE_MAX_COLOR_BUFS];
- struct pipe_transfer *zsbuf_transfer;
-
ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS];
ubyte *zsbuf_map;
- struct pipe_surface *tex_surf;
- uint *tex_map;
-
uint dirty;
uint dirty_textures; /* bitmask of texture units */
uint dirty_samplers; /* bitmask of sampler units */
diff --git a/src/gallium/drivers/cell/ppu/cell_fence.c b/src/gallium/drivers/cell/ppu/cell_fence.c
index 867b5dcaa0..32dbf5706c 100644
--- a/src/gallium/drivers/cell/ppu/cell_fence.c
+++ b/src/gallium/drivers/cell/ppu/cell_fence.c
@@ -153,16 +153,12 @@ cell_add_fenced_textures(struct cell_context *cell)
for (i = 0; i < cell->num_textures; i++) {
struct cell_texture *ct = cell->texture[i];
if (ct) {
- uint level;
- for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) {
- if (ct->tiled_buffer[level]) {
#if 0
- printf("Adding texture %p buffer %p to list\n",
- ct, ct->tiled_buffer[level]);
+ printf("Adding texture %p buffer %p to list\n",
+ ct, ct->tiled_buffer[level]);
#endif
- cell_add_buffer_to_list(cell, list, ct->tiled_buffer[level]);
- }
- }
+ if (ct->buffer)
+ cell_add_buffer_to_list(cell, list, ct->buffer);
}
}
}
diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c
index ff529fe22c..9479c0898f 100644
--- a/src/gallium/drivers/cell/ppu/cell_state_emit.c
+++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c
@@ -287,19 +287,23 @@ cell_emit_state(struct cell_context *cell)
for (i = 0;i < CELL_MAX_SAMPLERS; i++) {
if (cell->dirty_textures & (1 << i)) {
STATIC_ASSERT(sizeof(struct cell_command_texture) % 16 == 0);
- struct cell_command_texture *texture
- = (struct cell_command_texture *)cell_batch_alloc16(cell, sizeof(*texture));
+ struct cell_command_texture *texture =
+ (struct cell_command_texture *)
+ cell_batch_alloc16(cell, sizeof(*texture));
+
texture->opcode[0] = CELL_CMD_STATE_TEXTURE;
texture->unit = i;
if (cell->texture[i]) {
+ struct cell_texture *ct = cell->texture[i];
uint level;
for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) {
- texture->start[level] = cell->texture[i]->tiled_mapped[level];
- texture->width[level] = cell->texture[i]->base.width[level];
- texture->height[level] = cell->texture[i]->base.height[level];
- texture->depth[level] = cell->texture[i]->base.depth[level];
+ texture->start[level] = (ct->mapped +
+ ct->level_offset[level]);
+ texture->width[level] = ct->base.width[level];
+ texture->height[level] = ct->base.height[level];
+ texture->depth[level] = ct->base.depth[level];
}
- texture->target = cell->texture[i]->base.target;
+ texture->target = ct->base.target;
}
else {
uint level;
diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c
index fa52e2cbea..74724393f7 100644
--- a/src/gallium/drivers/cell/ppu/cell_texture.c
+++ b/src/gallium/drivers/cell/ppu/cell_texture.c
@@ -62,7 +62,7 @@ cell_texture_layout(struct cell_texture *ct)
ct->buffer_size = 0;
- for ( level = 0 ; level <= pt->last_level ; level++ ) {
+ for (level = 0; level <= pt->last_level; level++) {
unsigned size;
unsigned w_tile, h_tile;
@@ -90,7 +90,7 @@ cell_texture_layout(struct cell_texture *ct)
ct->buffer_size += size;
- width = minify(width);
+ width = minify(width);
height = minify(height);
depth = minify(depth);
}
@@ -131,33 +131,19 @@ cell_texture_release(struct pipe_screen *screen,
if (!*pt)
return;
- /*
- DBG("%s %p refcount will be %d\n",
- __FUNCTION__, (void *) *pt, (*pt)->refcount - 1);
- */
if (--(*pt)->refcount <= 0) {
/* Delete this texture now.
* But note that the underlying pipe_buffer may linger...
*/
struct cell_texture *ct = cell_texture(*pt);
- uint i;
- /*
- DBG("%s deleting %p\n", __FUNCTION__, (void *) ct);
- */
+ if (ct->mapped) {
+ pipe_buffer_unmap(screen, ct->buffer);
+ ct->mapped = NULL;
+ }
pipe_buffer_reference(screen, &ct->buffer, NULL);
- for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
- /* Unreference the tiled image buffer.
- * It may not actually be deleted until a fence is hit.
- */
- if (ct->tiled_buffer[i]) {
- ct->tiled_mapped[i] = NULL;
- pipe_buffer_reference(screen, &ct->tiled_buffer[i], NULL);
- }
- }
-
FREE(ct);
}
*pt = NULL;
@@ -294,107 +280,6 @@ untwiddle_image_uint(uint w, uint h, uint tile_size, uint *dst,
}
-/**
- * Convert linear texture image data to tiled format for SPU usage.
- */
-static void
-cell_twiddle_texture(struct pipe_screen *screen,
- struct pipe_surface *surface)
-{
-#if 0 // XXX fix me
- struct cell_texture *ct = cell_texture(surface->texture);
- const uint level = surface->level;
- const uint texWidth = ct->base.width[level];
- const uint texHeight = ct->base.height[level];
- const uint bufWidth = align(texWidth, TILE_SIZE);
- const uint bufHeight = align(texHeight, TILE_SIZE);
- const void *map = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_READ);
- const uint *src = (const uint *) map;
-
- switch (ct->base.format) {
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- case PIPE_FORMAT_S8Z24_UNORM:
- {
- int numFaces = ct->base.target == PIPE_TEXTURE_CUBE ? 6 : 1;
- int offset = bufWidth * bufHeight * 4 * surface->face;
- uint *dst;
-
- if (!ct->tiled_buffer[level]) {
- /* allocate buffer for tiled data now */
- struct pipe_winsys *ws = screen->winsys;
- uint bytes = bufWidth * bufHeight * 4 * numFaces;
- ct->tiled_buffer[level] =
- ws->buffer_create(ws, 16, PIPE_BUFFER_USAGE_PIXEL, bytes);
- /* and map it */
- ct->tiled_mapped[level] =
- ws->buffer_map(ws, ct->tiled_buffer[level],
- PIPE_BUFFER_USAGE_GPU_READ);
- }
- dst = (uint *) ((ubyte *) ct->tiled_mapped[level] + offset);
-
- twiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst,
- surface->stride, src);
- }
- break;
- default:
- printf("Cell: twiddle unsupported texture format %s\n",
- pf_name(ct->base.format));
- }
-
- screen->surface_unmap(screen, surface);
-#endif
-}
-
-
-/**
- * Convert SPU tiled texture image data to linear format for app usage.
- */
-static void
-cell_untwiddle_texture(struct pipe_screen *screen,
- struct pipe_surface *surface)
-{
-#if 0 // XXX fix me
- struct cell_texture *ct = cell_texture(surface->texture);
- const uint level = surface->level;
- const uint texWidth = ct->base.width[level];
- const uint texHeight = ct->base.height[level];
- const void *map = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_READ);
- const uint *src = (const uint *) ((const ubyte *) map + surface->offset);
-
- switch (ct->base.format) {
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_B8G8R8A8_UNORM:
- case PIPE_FORMAT_S8Z24_UNORM:
- {
- int numFaces = ct->base.target == PIPE_TEXTURE_CUBE ? 6 : 1;
- int offset = surface->stride * texHeight * 4 * surface->face;
- uint *dst;
-
- if (!ct->untiled_data[level]) {
- ct->untiled_data[level] =
- align_malloc(surface->stride * texHeight * 4 * numFaces, 16);
- }
-
- dst = (uint *) ((ubyte *) ct->untiled_data[level] + offset);
-
- untwiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst,
- surface->stride, src);
- }
- break;
- default:
- {
- ct->untiled_data[level] = NULL;
- printf("Cell: untwiddle unsupported texture format %s\n",
- pf_name(ct->base.format));
- }
- }
-
- screen->surface_unmap(screen, surface);
-#endif
-}
-
-
static struct pipe_surface *
cell_get_tex_surface(struct pipe_screen *screen,
struct pipe_texture *pt,
@@ -409,38 +294,25 @@ cell_get_tex_surface(struct pipe_screen *screen,
ps->refcount = 1;
pipe_texture_reference(&ps->texture, pt);
ps->format = pt->format;
- //ps->block = pt->block;
ps->width = pt->width[level];
ps->height = pt->height[level];
- //ps->nblocksx = pt->nblocksx[level];
- //ps->nblocksy = pt->nblocksy[level];
- //ps->stride = ct->stride[level];
ps->offset = ct->level_offset[level];
- ps->usage = usage;
-
/* XXX may need to override usage flags (see sp_texture.c) */
-
- pipe_texture_reference(&ps->texture, pt);
+ ps->usage = usage;
ps->face = face;
ps->level = level;
ps->zslice = zslice;
- if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) {
-#if 0 // XXX fix me
- ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) *
- ps->nblocksy *
- ps->stride;
-#endif
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ ps->offset += face * pt->nblocksy[level] * ct->stride[level];
+ }
+ else if (pt->target == PIPE_TEXTURE_3D) {
+ ps->offset += zslice * pt->nblocksy[level] * ct->stride[level];
}
else {
assert(face == 0);
assert(zslice == 0);
}
-
- if (ps->usage & PIPE_BUFFER_USAGE_CPU_READ) {
- /* convert from tiled to linear layout */
- cell_untwiddle_texture(screen, ps);
- }
}
return ps;
}
@@ -450,24 +322,8 @@ static void
cell_tex_surface_release(struct pipe_screen *screen,
struct pipe_surface **s)
{
- struct cell_texture *ct = cell_texture((*s)->texture);
- const uint level = (*s)->level;
struct pipe_surface *surf = *s;
- if ((surf->usage & PIPE_BUFFER_USAGE_CPU_READ) && (ct->untiled_data[level]))
- {
- align_free(ct->untiled_data[level]);
- ct->untiled_data[level] = NULL;
- }
-
- if ((ct->base.tex_usage & PIPE_TEXTURE_USAGE_SAMPLER) &&
- (surf->usage & PIPE_BUFFER_USAGE_CPU_WRITE)) {
- /* convert from linear to tiled layout */
- cell_twiddle_texture(screen, surf);
- }
-
- /* XXX if done rendering to teximage, re-tile */
-
if (--surf->refcount == 0) {
pipe_texture_reference(&surf->texture, NULL);
FREE(surf);
@@ -476,6 +332,11 @@ cell_tex_surface_release(struct pipe_screen *screen,
}
+/**
+ * Create new pipe_transfer object.
+ * This is used by the user to put tex data into a texture (and get it
+ * back out for glGetTexImage).
+ */
static struct pipe_transfer *
cell_get_tex_transfer(struct pipe_screen *screen,
struct pipe_texture *texture,
@@ -485,14 +346,13 @@ cell_get_tex_transfer(struct pipe_screen *screen,
{
struct cell_texture *ct = cell_texture(texture);
struct cell_transfer *ctrans;
- struct pipe_transfer *pt;
assert(texture);
assert(level <= texture->last_level);
ctrans = CALLOC_STRUCT(cell_transfer);
- pt = &ctrans->base;
if (ctrans) {
+ struct pipe_transfer *pt = &ctrans->base;
pt->refcount = 1;
pipe_texture_reference(&pt->texture, texture);
pt->format = texture->format;
@@ -504,23 +364,26 @@ cell_get_tex_transfer(struct pipe_screen *screen,
pt->nblocksx = texture->nblocksx[level];
pt->nblocksy = texture->nblocksy[level];
pt->stride = ct->stride[level];
- ctrans->offset = ct->level_offset[level];
pt->usage = usage;
pt->face = face;
pt->level = level;
pt->zslice = zslice;
- if (texture->target == PIPE_TEXTURE_CUBE ||
- texture->target == PIPE_TEXTURE_3D) {
- ctrans->offset += ((texture->target == PIPE_TEXTURE_CUBE) ? face :
- zslice) * pt->nblocksy * pt->stride;
+ ctrans->offset = ct->level_offset[level];
+
+ if (texture->target == PIPE_TEXTURE_CUBE) {
+ ctrans->offset += face * pt->nblocksy * pt->stride;
+ }
+ else if (texture->target == PIPE_TEXTURE_3D) {
+ ctrans->offset += zslice * pt->nblocksy * pt->stride;
}
else {
assert(face == 0);
assert(zslice == 0);
}
+ return pt;
}
- return pt;
+ return NULL;
}
@@ -542,16 +405,23 @@ cell_tex_transfer_release(struct pipe_screen *screen,
}
+/**
+ * Return pointer to texture image data in linear layout.
+ */
static void *
-cell_transfer_map( struct pipe_screen *screen,
- struct pipe_transfer *transfer )
+cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer)
{
- ubyte *map;
- struct cell_texture *spt;
- unsigned flags = 0;
+ struct cell_transfer *ctrans = cell_transfer(transfer);
+ struct pipe_texture *pt = transfer->texture;
+ struct cell_texture *ct = cell_texture(pt);
+ const uint level = ctrans->base.level;
+ const uint texWidth = pt->width[level];
+ const uint texHeight = pt->height[level];
+ const uint stride = ct->stride[level];
+ unsigned flags = 0x0;
+ unsigned size;
assert(transfer->texture);
- spt = cell_texture(transfer->texture);
if (transfer->usage != PIPE_TRANSFER_READ) {
flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
@@ -561,89 +431,82 @@ cell_transfer_map( struct pipe_screen *screen,
flags |= PIPE_BUFFER_USAGE_CPU_READ;
}
- map = pipe_buffer_map(screen, spt->buffer, flags);
- if (map == NULL)
- return NULL;
+ if (!ct->mapped) {
+ /* map now */
+ ct->mapped = pipe_buffer_map(screen, ct->buffer, flags);
+ }
- /* May want to different things here depending on read/write nature
- * of the map:
+ /*
+ * Create a buffer of ordinary memory for the linear texture.
+ * This is the memory that the user will read/write.
*/
- if (transfer->texture && transfer->usage != PIPE_TRANSFER_READ)
- {
- /* Do something to notify sharing contexts of a texture change.
- * In cell, that would mean flushing the texture cache.
- */
-#if 00
- cell_screen(screen)->timestamp++;
-#endif
+ size = pt->nblocksx[level] * pt->nblocksy[level] * pt->block.size;
+
+ ctrans->map = align_malloc(size, 16);
+ if (!ctrans->map)
+ return NULL; /* out of memory */
+
+ if (transfer->usage & PIPE_TRANSFER_READ) {
+ /* need to untwiddle the texture to make a linear version */
+ const uint bpp = pf_get_size(ct->base.format);
+ if (bpp == 4) {
+ const uint *src = (uint *) (ct->mapped + ctrans->offset);
+ uint *dst = ctrans->map;
+ untwiddle_image_uint(texWidth, texHeight, TILE_SIZE,
+ dst, stride, src);
+ }
+ else {
+ // xxx fix
+ }
}
-
- return map + cell_transfer(transfer)->offset +
- transfer->y / transfer->block.height * transfer->stride +
- transfer->x / transfer->block.width * transfer->block.size;
+
+ return ctrans->map;
}
+/**
+ * Called when user is done reading/writing texture data.
+ * If new data was written, this is where we convert the linear data
+ * to tiled data.
+ */
static void
cell_transfer_unmap(struct pipe_screen *screen,
- struct pipe_transfer *transfer)
+ struct pipe_transfer *transfer)
{
- struct cell_texture *spt;
-
- assert(transfer->texture);
- spt = cell_texture(transfer->texture);
-
- pipe_buffer_unmap( screen, spt->buffer );
-}
-
-
-static void *
-cell_surface_map(struct pipe_screen *screen,
- struct pipe_surface *surface,
- unsigned flags)
-{
- ubyte *map;
- struct cell_texture *ct = cell_texture(surface->texture);
- const uint level = surface->level;
-
- assert(ct);
-
-#if 0
- if (flags & ~surface->usage) {
- assert(0);
- return NULL;
+ struct cell_transfer *ctrans = cell_transfer(transfer);
+ struct pipe_texture *pt = transfer->texture;
+ struct cell_texture *ct = cell_texture(pt);
+ const uint level = ctrans->base.level;
+ const uint texWidth = pt->width[level];
+ const uint texHeight = pt->height[level];
+ const uint stride = ct->stride[level];
+
+ if (!ct->mapped) {
+ /* map now */
+ ct->mapped = pipe_buffer_map(screen, ct->buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
}
-#endif
- map = pipe_buffer_map( screen, ct->buffer, flags );
- if (map == NULL) {
- return NULL;
- }
- else {
- if ((surface->usage & PIPE_BUFFER_USAGE_CPU_READ) &&
- (ct->untiled_data[level])) {
- return (void *) ((ubyte *) ct->untiled_data[level] + surface->offset);
+ if (transfer->usage & PIPE_TRANSFER_WRITE) {
+ /* The user wrote new texture data into the mapped buffer.
+ * We need to convert the new linear data into the twiddled/tiled format.
+ */
+ const uint bpp = pf_get_size(ct->base.format);
+ if (bpp == 4) {
+ const uint *src = ctrans->map;
+ uint *dst = (uint *) (ct->mapped + ctrans->offset);
+ twiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst, stride, src);
}
else {
- return (void *) (map + surface->offset);
+ // xxx fix
}
}
-}
-
-
-static void
-cell_surface_unmap(struct pipe_screen *screen,
- struct pipe_surface *surface)
-{
- struct cell_texture *ct = cell_texture(surface->texture);
-
- assert(ct);
- pipe_buffer_unmap( screen, ct->buffer );
+ align_free(ctrans->map);
+ ctrans->map = NULL;
}
-
void
cell_init_screen_texture_funcs(struct pipe_screen *screen)
{
@@ -655,6 +518,7 @@ cell_init_screen_texture_funcs(struct pipe_screen *screen)
screen->get_tex_transfer = cell_get_tex_transfer;
screen->tex_transfer_release = cell_tex_transfer_release;
+
screen->transfer_map = cell_transfer_map;
screen->transfer_unmap = cell_transfer_unmap;
}
diff --git a/src/gallium/drivers/cell/ppu/cell_texture.h b/src/gallium/drivers/cell/ppu/cell_texture.h
index fc6486adbe..3ffc0bfdb5 100644
--- a/src/gallium/drivers/cell/ppu/cell_texture.h
+++ b/src/gallium/drivers/cell/ppu/cell_texture.h
@@ -43,20 +43,14 @@ struct cell_texture
unsigned long level_offset[CELL_MAX_TEXTURE_LEVELS];
unsigned long stride[CELL_MAX_TEXTURE_LEVELS];
- /* The data is held here:
- */
+ /** The tiled texture data is held in this buffer */
struct pipe_buffer *buffer;
unsigned long buffer_size;
- /** Texture data in tiled layout is held here */
- struct pipe_buffer *tiled_buffer[CELL_MAX_TEXTURE_LEVELS];
- /** Mapped, tiled texture data */
- void *tiled_mapped[CELL_MAX_TEXTURE_LEVELS];
-
- struct pipe_transfer *transfer;
-
- /** The original, linear texture data */
- void *untiled_data[CELL_MAX_TEXTURE_LEVELS];
+ /** The buffer above, mapped. This is the memory from which the
+ * SPUs will fetch texels. This texture data is in the tiled layout.
+ */
+ ubyte *mapped;
};
@@ -65,6 +59,7 @@ struct cell_transfer
struct pipe_transfer base;
unsigned long offset;
+ void *map;
};