summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/cell/ppu
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/cell/ppu')
-rw-r--r--src/gallium/drivers/cell/ppu/cell_clear.c6
-rw-r--r--src/gallium/drivers/cell/ppu/cell_context.h3
-rw-r--r--src/gallium/drivers/cell/ppu/cell_fence.c18
-rw-r--r--src/gallium/drivers/cell/ppu/cell_pipe_state.c95
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_emit.c18
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_shader.c4
-rw-r--r--src/gallium/drivers/cell/ppu/cell_surface.c14
-rw-r--r--src/gallium/drivers/cell/ppu/cell_texture.c377
-rw-r--r--src/gallium/drivers/cell/ppu/cell_texture.h28
-rw-r--r--src/gallium/drivers/cell/ppu/cell_vbuf.c33
10 files changed, 327 insertions, 269 deletions
diff --git a/src/gallium/drivers/cell/ppu/cell_clear.c b/src/gallium/drivers/cell/ppu/cell_clear.c
index c2e2769..edc0674 100644
--- a/src/gallium/drivers/cell/ppu/cell_clear.c
+++ b/src/gallium/drivers/cell/ppu/cell_clear.c
@@ -70,18 +70,12 @@ void
cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps,
unsigned clearValue)
{
- struct pipe_screen *screen = pipe->screen;
struct cell_context *cell = cell_context(pipe);
uint surfIndex;
if (cell->dirty)
cell_update_derived(cell);
-
- if (!cell->cbuf_map[0])
- cell->cbuf_map[0] = screen->surface_map(screen, ps,
- PIPE_BUFFER_USAGE_GPU_WRITE);
-
if (ps == cell->framebuffer.zsbuf) {
/* clear z/stencil buffer */
surfIndex = 1;
diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h
index eb1397b..5c3188e 100644
--- a/src/gallium/drivers/cell/ppu/cell_context.h
+++ b/src/gallium/drivers/cell/ppu/cell_context.h
@@ -130,9 +130,6 @@ struct cell_context
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 867b5dc..13125a9 100644
--- a/src/gallium/drivers/cell/ppu/cell_fence.c
+++ b/src/gallium/drivers/cell/ppu/cell_fence.c
@@ -96,7 +96,7 @@ cell_add_buffer_to_list(struct cell_context *cell,
struct cell_buffer_node *node = CALLOC_STRUCT(cell_buffer_node);
/* create new list node which references the buffer, insert at head */
if (node) {
- pipe_buffer_reference(ps, &node->buffer, buffer);
+ pipe_buffer_reference(&node->buffer, buffer);
node->next = list->head;
list->head = node;
}
@@ -127,10 +127,10 @@ cell_free_fenced_buffers(struct cell_context *cell,
pipe_buffer_unmap(ps, node->buffer);
#if 0
printf("Unref buffer %p\n", node->buffer);
- if (node->buffer->refcount == 1)
+ if (node->buffer->reference.count == 1)
printf(" Delete!\n");
#endif
- pipe_buffer_reference(ps, &node->buffer, NULL);
+ pipe_buffer_reference(&node->buffer, NULL);
FREE(node);
node = next;
}
@@ -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_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c
index ca358ed..ccd0fef 100644
--- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c
+++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c
@@ -253,10 +253,13 @@ cell_set_sampler_textures(struct pipe_context *pipe,
assert(num <= CELL_MAX_SAMPLERS);
for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
- struct pipe_texture *new_tex = i < num ? texture[i] : NULL;
- if ((struct pipe_texture *) cell->texture[i] != new_tex) {
+ struct cell_texture *new_tex = cell_texture(i < num ? texture[i] : NULL);
+ struct cell_texture *old_tex = cell->texture[i];
+ if (old_tex != new_tex) {
+
pipe_texture_reference((struct pipe_texture **) &cell->texture[i],
- new_tex);
+ (struct pipe_texture *) new_tex);
+
changed |= (1 << i);
}
}
@@ -270,6 +273,70 @@ cell_set_sampler_textures(struct pipe_context *pipe,
}
+/**
+ * Map color and z/stencil framebuffer surfaces.
+ */
+static void
+cell_map_surfaces(struct cell_context *cell)
+{
+ struct pipe_screen *screen = cell->pipe.screen;
+ uint i;
+
+ for (i = 0; i < 1; i++) {
+ struct pipe_surface *ps = cell->framebuffer.cbufs[i];
+ if (ps) {
+ struct cell_texture *ct = cell_texture(ps->texture);
+ cell->cbuf_map[i] = screen->buffer_map(screen,
+ ct->buffer,
+ (PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE));
+ }
+ }
+
+ {
+ struct pipe_surface *ps = cell->framebuffer.zsbuf;
+ if (ps) {
+ struct cell_texture *ct = cell_texture(ps->texture);
+ cell->zsbuf_map = screen->buffer_map(screen,
+ ct->buffer,
+ (PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE));
+ }
+ }
+}
+
+
+/**
+ * Unmap color and z/stencil framebuffer surfaces.
+ */
+static void
+cell_unmap_surfaces(struct cell_context *cell)
+{
+ struct pipe_screen *screen = cell->pipe.screen;
+ uint i;
+
+ for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+ struct pipe_surface *ps = cell->framebuffer.cbufs[i];
+ if (ps && cell->cbuf_map[i]) {
+ struct cell_texture *ct = cell_texture(ps->texture);
+ assert(ps->texture);
+ assert(ct->buffer);
+
+ screen->buffer_unmap(screen, ct->buffer);
+ cell->cbuf_map[i] = NULL;
+ }
+ }
+
+ {
+ struct pipe_surface *ps = cell->framebuffer.zsbuf;
+ if (ps && cell->zsbuf_map) {
+ struct cell_texture *ct = cell_texture(ps->texture);
+ screen->buffer_unmap(screen, ct->buffer);
+ cell->zsbuf_map = NULL;
+ }
+ }
+}
+
static void
cell_set_framebuffer_state(struct pipe_context *pipe,
@@ -278,24 +345,10 @@ cell_set_framebuffer_state(struct pipe_context *pipe,
struct cell_context *cell = cell_context(pipe);
if (1 /*memcmp(&cell->framebuffer, fb, sizeof(*fb))*/) {
- struct pipe_surface *csurf = fb->cbufs[0];
- struct pipe_surface *zsurf = fb->zsbuf;
uint i;
- uint flags = (PIPE_BUFFER_USAGE_GPU_WRITE |
- PIPE_BUFFER_USAGE_GPU_READ);
/* unmap old surfaces */
- for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
- if (cell->framebuffer.cbufs[i] && cell->cbuf_map[i]) {
- pipe_surface_unmap(cell->framebuffer.cbufs[i]);
- cell->cbuf_map[i] = NULL;
- }
- }
-
- if (cell->framebuffer.zsbuf && cell->zsbuf_map) {
- pipe_surface_unmap(cell->framebuffer.zsbuf);
- cell->zsbuf_map = NULL;
- }
+ cell_unmap_surfaces(cell);
/* Finish any pending rendering to the current surface before
* installing a new surface!
@@ -314,11 +367,7 @@ cell_set_framebuffer_state(struct pipe_context *pipe,
pipe_surface_reference(&cell->framebuffer.zsbuf, fb->zsbuf);
/* map new surfaces */
- if (csurf)
- cell->cbuf_map[0] = pipe_surface_map(csurf, flags);
-
- if (zsurf)
- cell->zsbuf_map = pipe_surface_map(zsurf, flags);
+ cell_map_surfaces(cell);
cell->dirty |= CELL_NEW_FRAMEBUFFER;
}
diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c
index ff529fe..9479c08 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_state_shader.c b/src/gallium/drivers/cell/ppu/cell_state_shader.c
index bf517ea..6568c78 100644
--- a/src/gallium/drivers/cell/ppu/cell_state_shader.c
+++ b/src/gallium/drivers/cell/ppu/cell_state_shader.c
@@ -193,9 +193,7 @@ cell_set_constant_buffer(struct pipe_context *pipe,
draw_flush(cell->draw);
/* note: reference counting */
- pipe_buffer_reference(pipe->screen,
- &cell->constants[shader].buffer,
- buf->buffer);
+ pipe_buffer_reference(&cell->constants[shader].buffer, buf->buffer);
if (shader == PIPE_SHADER_VERTEX)
cell->dirty |= CELL_NEW_VS_CONSTANTS;
diff --git a/src/gallium/drivers/cell/ppu/cell_surface.c b/src/gallium/drivers/cell/ppu/cell_surface.c
index c9203fe..ffb8595 100644
--- a/src/gallium/drivers/cell/ppu/cell_surface.c
+++ b/src/gallium/drivers/cell/ppu/cell_surface.c
@@ -30,9 +30,21 @@
#include "cell_surface.h"
+static void
+cell_surface_copy(struct pipe_context *pipe,
+ struct pipe_surface *dest, unsigned destx, unsigned desty,
+ struct pipe_surface *src, unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+ util_surface_copy(pipe, FALSE,
+ dest, destx, desty,
+ src, srcx, srcy,
+ width, height);
+}
+
void
cell_init_surface_functions(struct cell_context *cell)
{
- cell->pipe.surface_copy = util_surface_copy;
+ cell->pipe.surface_copy = cell_surface_copy;
cell->pipe.surface_fill = util_surface_fill;
}
diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c
index 9ba995a..e265944 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);
}
@@ -101,18 +101,17 @@ static struct pipe_texture *
cell_texture_create(struct pipe_screen *screen,
const struct pipe_texture *templat)
{
- struct pipe_winsys *ws = screen->winsys;
struct cell_texture *ct = CALLOC_STRUCT(cell_texture);
if (!ct)
return NULL;
ct->base = *templat;
- ct->base.refcount = 1;
+ pipe_reference_init(&ct->base.reference, 1);
ct->base.screen = screen;
cell_texture_layout(ct);
- ct->buffer = ws->buffer_create(ws, 32, PIPE_BUFFER_USAGE_PIXEL,
+ ct->buffer = screen->buffer_create(screen, 32, PIPE_BUFFER_USAGE_PIXEL,
ct->buffer_size);
if (!ct->buffer) {
@@ -125,42 +124,18 @@ cell_texture_create(struct pipe_screen *screen,
static void
-cell_texture_release(struct pipe_screen *screen,
- struct pipe_texture **pt)
+cell_texture_destroy(struct pipe_texture *pt)
{
- 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;
+ struct cell_texture *ct = cell_texture(pt);
- /*
- DBG("%s deleting %p\n", __FUNCTION__, (void *) ct);
- */
+ if (ct->mapped) {
+ pipe_buffer_unmap(ct->buffer->screen, ct->buffer);
+ ct->mapped = NULL;
+ }
- pipe_buffer_reference(screen, &ct->buffer, NULL);
+ pipe_buffer_reference(&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;
+ FREE(ct);
}
@@ -294,103 +269,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)
-{
- 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);
-}
-
-
-/**
- * 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)
-{
- 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);
-}
-
-
static struct pipe_surface *
cell_get_tex_surface(struct pipe_screen *screen,
struct pipe_texture *pt,
@@ -402,130 +280,223 @@ cell_get_tex_surface(struct pipe_screen *screen,
ps = CALLOC_STRUCT(pipe_surface);
if (ps) {
- ps->refcount = 1;
+ pipe_reference_init(&ps->reference, 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) {
- ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) *
- ps->nblocksy *
- ps->stride;
+ 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;
}
static void
-cell_tex_surface_release(struct pipe_screen *screen,
- struct pipe_surface **s)
+cell_tex_surface_destroy(struct pipe_surface *surf)
{
- 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;
- }
+ pipe_texture_reference(&surf->texture, NULL);
+ FREE(surf);
+}
- 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);
+
+/**
+ * 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,
+ unsigned face, unsigned level, unsigned zslice,
+ enum pipe_transfer_usage usage,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct cell_texture *ct = cell_texture(texture);
+ struct cell_transfer *ctrans;
+
+ assert(texture);
+ assert(level <= texture->last_level);
+
+ ctrans = CALLOC_STRUCT(cell_transfer);
+ if (ctrans) {
+ struct pipe_transfer *pt = &ctrans->base;
+ pipe_texture_reference(&pt->texture, texture);
+ pt->format = texture->format;
+ pt->block = texture->block;
+ pt->x = x;
+ pt->y = y;
+ pt->width = w;
+ pt->height = h;
+ pt->nblocksx = texture->nblocksx[level];
+ pt->nblocksy = texture->nblocksy[level];
+ pt->stride = ct->stride[level];
+ pt->usage = usage;
+ pt->face = face;
+ pt->level = level;
+ pt->zslice = zslice;
+
+ 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 NULL;
+}
- /* XXX if done rendering to teximage, re-tile */
- if (--surf->refcount == 0) {
- pipe_texture_reference(&surf->texture, NULL);
- FREE(surf);
- }
- *s = NULL;
+static void
+cell_tex_transfer_destroy(struct pipe_transfer *t)
+{
+ struct cell_transfer *transfer = cell_transfer(t);
+ /* 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 cell, nothing to do.
+ */
+ assert (transfer->base.texture);
+ pipe_texture_reference(&transfer->base.texture, NULL);
+ FREE(transfer);
}
+/**
+ * Return pointer to texture image data in linear layout.
+ */
static void *
-cell_surface_map(struct pipe_screen *screen,
- struct pipe_surface *surface,
- unsigned flags)
+cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer)
{
- ubyte *map;
- struct cell_texture *ct = cell_texture(surface->texture);
- const uint level = surface->level;
+ 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(ct);
+ assert(transfer->texture);
-#if 0
- if (flags & ~surface->usage) {
- assert(0);
- return NULL;
+ if (transfer->usage != PIPE_TRANSFER_READ) {
+ flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
}
-#endif
- map = pipe_buffer_map( screen, ct->buffer, flags );
- if (map == NULL) {
- return NULL;
+ if (transfer->usage != PIPE_TRANSFER_WRITE) {
+ flags |= PIPE_BUFFER_USAGE_CPU_READ;
+ }
+
+ if (!ct->mapped) {
+ /* map now */
+ ct->mapped = pipe_buffer_map(screen, ct->buffer, flags);
}
- else {
- if ((surface->usage & PIPE_BUFFER_USAGE_CPU_READ) &&
- (ct->untiled_data[level])) {
- return (void *) ((ubyte *) ct->untiled_data[level] + surface->offset);
+
+ /*
+ * Create a buffer of ordinary memory for the linear texture.
+ * This is the memory that the user will read/write.
+ */
+ 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 {
- return (void *) (map + surface->offset);
+ // xxx fix
}
}
+
+ 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_surface_unmap(struct pipe_screen *screen,
- struct pipe_surface *surface)
+cell_transfer_unmap(struct pipe_screen *screen,
+ struct pipe_transfer *transfer)
{
- struct cell_texture *ct = cell_texture(surface->texture);
+ 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);
+ }
- assert(ct);
+ 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 {
+ // xxx fix
+ }
+ }
- pipe_buffer_unmap( screen, ct->buffer );
+ align_free(ctrans->map);
+ ctrans->map = NULL;
}
-
void
cell_init_screen_texture_funcs(struct pipe_screen *screen)
{
screen->texture_create = cell_texture_create;
- screen->texture_release = cell_texture_release;
+ screen->texture_destroy = cell_texture_destroy;
screen->get_tex_surface = cell_get_tex_surface;
- screen->tex_surface_release = cell_tex_surface_release;
+ screen->tex_surface_destroy = cell_tex_surface_destroy;
+
+ screen->get_tex_transfer = cell_get_tex_transfer;
+ screen->tex_transfer_destroy = cell_tex_transfer_destroy;
- screen->surface_map = cell_surface_map;
- screen->surface_unmap = cell_surface_unmap;
+ 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 7018b0c..3ffc0bf 100644
--- a/src/gallium/drivers/cell/ppu/cell_texture.h
+++ b/src/gallium/drivers/cell/ppu/cell_texture.h
@@ -43,16 +43,23 @@ 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];
- 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;
+};
+
+
+struct cell_transfer
+{
+ struct pipe_transfer base;
+
+ unsigned long offset;
+ void *map;
};
@@ -64,6 +71,13 @@ cell_texture(struct pipe_texture *pt)
}
+/** cast wrapper */
+static INLINE struct cell_transfer *
+cell_transfer(struct pipe_transfer *pt)
+{
+ return (struct cell_transfer *) pt;
+}
+
extern void
cell_init_screen_texture_funcs(struct pipe_screen *screen);
diff --git a/src/gallium/drivers/cell/ppu/cell_vbuf.c b/src/gallium/drivers/cell/ppu/cell_vbuf.c
index ab54e79..cfaffb5 100644
--- a/src/gallium/drivers/cell/ppu/cell_vbuf.c
+++ b/src/gallium/drivers/cell/ppu/cell_vbuf.c
@@ -62,6 +62,7 @@ struct cell_vbuf_render
uint vertex_size; /**< in bytes */
void *vertex_buffer; /**< just for debug, really */
uint vertex_buf; /**< in [0, CELL_NUM_BUFFERS-1] */
+ uint vertex_buffer_size; /**< size in bytes */
};
@@ -82,24 +83,26 @@ cell_vbuf_get_vertex_info(struct vbuf_render *vbr)
}
-static void *
+static boolean
cell_vbuf_allocate_vertices(struct vbuf_render *vbr,
ushort vertex_size, ushort nr_vertices)
{
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
+ unsigned size = vertex_size * nr_vertices;
/*printf("Alloc verts %u * %u\n", vertex_size, nr_vertices);*/
assert(cvbr->vertex_buf == ~0);
cvbr->vertex_buf = cell_get_empty_buffer(cvbr->cell);
cvbr->vertex_buffer = cvbr->cell->buffer[cvbr->vertex_buf];
+ cvbr->vertex_buffer_size = size;
cvbr->vertex_size = vertex_size;
- return cvbr->vertex_buffer;
+
+ return cvbr->vertex_buffer != NULL;
}
static void
-cell_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices,
- unsigned vertex_size, unsigned vertices_used)
+cell_vbuf_release_vertices(struct vbuf_render *vbr)
{
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
struct cell_context *cell = cvbr->cell;
@@ -127,11 +130,29 @@ cell_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices,
cvbr->vertex_buf = ~0;
cell_flush_int(cell, 0x0);
- assert(vertices == cvbr->vertex_buffer);
cvbr->vertex_buffer = NULL;
}
+static void *
+cell_vbuf_map_vertices(struct vbuf_render *vbr)
+{
+ struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
+ return cvbr->vertex_buffer;
+}
+
+
+static void
+cell_vbuf_unmap_vertices(struct vbuf_render *vbr,
+ ushort min_index,
+ ushort max_index )
+{
+ struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
+ assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size );
+ /* do nothing */
+}
+
+
static boolean
cell_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
@@ -295,6 +316,8 @@ cell_init_vbuf(struct cell_context *cell)
cell->vbuf_render->base.get_vertex_info = cell_vbuf_get_vertex_info;
cell->vbuf_render->base.allocate_vertices = cell_vbuf_allocate_vertices;
+ cell->vbuf_render->base.map_vertices = cell_vbuf_map_vertices;
+ cell->vbuf_render->base.unmap_vertices = cell_vbuf_unmap_vertices;
cell->vbuf_render->base.set_primitive = cell_vbuf_set_primitive;
cell->vbuf_render->base.draw = cell_vbuf_draw;
cell->vbuf_render->base.release_vertices = cell_vbuf_release_vertices;