diff options
Diffstat (limited to 'src/gallium/drivers/cell')
-rw-r--r-- | src/gallium/drivers/cell/ppu/cell_clear.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/cell/ppu/cell_context.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/cell/ppu/cell_fence.c | 18 | ||||
-rw-r--r-- | src/gallium/drivers/cell/ppu/cell_pipe_state.c | 95 | ||||
-rw-r--r-- | src/gallium/drivers/cell/ppu/cell_state_emit.c | 18 | ||||
-rw-r--r-- | src/gallium/drivers/cell/ppu/cell_state_shader.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/cell/ppu/cell_surface.c | 14 | ||||
-rw-r--r-- | src/gallium/drivers/cell/ppu/cell_texture.c | 377 | ||||
-rw-r--r-- | src/gallium/drivers/cell/ppu/cell_texture.h | 28 | ||||
-rw-r--r-- | src/gallium/drivers/cell/ppu/cell_vbuf.c | 33 | ||||
-rw-r--r-- | src/gallium/drivers/cell/spu/Makefile | 5 | ||||
-rw-r--r-- | src/gallium/drivers/cell/spu/spu_tri.c | 179 | ||||
-rw-r--r-- | src/gallium/drivers/cell/spu/spu_util.c | 2 |
13 files changed, 418 insertions, 364 deletions
diff --git a/src/gallium/drivers/cell/ppu/cell_clear.c b/src/gallium/drivers/cell/ppu/cell_clear.c index c2e276988c..edc06747ac 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 eb1397bb3f..5c3188e7f9 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 867b5dcaa0..13125a9fa3 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 ca358ed031..ccd0fef6e8 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 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_state_shader.c b/src/gallium/drivers/cell/ppu/cell_state_shader.c index bf517ea563..6568c784fe 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 c9203fee08..ffb8595d82 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 9ba995ab7d..e26594448f 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 7018b0c9bf..3ffc0bfdb5 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 ab54e79689..cfaffb52a8 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; diff --git a/src/gallium/drivers/cell/spu/Makefile b/src/gallium/drivers/cell/spu/Makefile index 116453b79c..3cc52301da 100644 --- a/src/gallium/drivers/cell/spu/Makefile +++ b/src/gallium/drivers/cell/spu/Makefile @@ -33,9 +33,10 @@ OLD_SOURCES = \ spu_vertex_shader.c -SPU_OBJECTS = $(SOURCES:.c=.o) \ +SPU_OBJECTS = $(SOURCES:.c=.o) + +SPU_ASM_OUT = $(SOURCES:.c=.s) -SPU_ASM_OUT = $(SOURCES:.c=.s) \ INCLUDE_DIRS = \ -I$(TOP)/src/mesa \ diff --git a/src/gallium/drivers/cell/spu/spu_tri.c b/src/gallium/drivers/cell/spu/spu_tri.c index 0d9fcb9997..d727268475 100644 --- a/src/gallium/drivers/cell/spu/spu_tri.c +++ b/src/gallium/drivers/cell/spu/spu_tri.c @@ -29,7 +29,6 @@ * Triangle rendering within a tile. */ -#include <transpose_matrix4x4.h> #include "pipe/p_compiler.h" #include "pipe/p_format.h" #include "util/u_math.h" @@ -71,6 +70,12 @@ struct vertex_header { #define MASK_ALL 0xf +#define CHAN0 0 +#define CHAN1 1 +#define CHAN2 2 +#define CHAN3 3 + + #define DEBUG_VERTS 0 /** @@ -144,99 +149,97 @@ struct setup_stage { static struct setup_stage setup; -/** - * Evaluate attribute coefficients (plane equations) to compute - * attribute values for the four fragments in a quad. - * Eg: four colors will be computed (in AoS format). - */ -static INLINE void -eval_coeff(uint slot, float x, float y, vector float w, vector float result[4]) +static INLINE vector float +splatx(vector float v) { - switch (spu.vertex_info.attrib[slot].interp_mode) { - case INTERP_CONSTANT: - result[QUAD_TOP_LEFT] = - result[QUAD_TOP_RIGHT] = - result[QUAD_BOTTOM_LEFT] = - result[QUAD_BOTTOM_RIGHT] = setup.coef[slot].a0; - break; - case INTERP_LINEAR: - { - vector float dadx = setup.coef[slot].dadx; - vector float dady = setup.coef[slot].dady; - vector float topLeft = - spu_add(setup.coef[slot].a0, - spu_add(spu_mul(spu_splats(x), dadx), - spu_mul(spu_splats(y), dady))); - - result[QUAD_TOP_LEFT] = topLeft; - result[QUAD_TOP_RIGHT] = spu_add(topLeft, dadx); - result[QUAD_BOTTOM_LEFT] = spu_add(topLeft, dady); - result[QUAD_BOTTOM_RIGHT] = spu_add(spu_add(topLeft, dadx), dady); - } - break; - case INTERP_PERSPECTIVE: - { - vector float dadx = setup.coef[slot].dadx; - vector float dady = setup.coef[slot].dady; - vector float topLeft = - spu_add(setup.coef[slot].a0, - spu_add(spu_mul(spu_splats(x), dadx), - spu_mul(spu_splats(y), dady))); - - vector float wInv = spu_re(w); /* 1.0 / w */ - - result[QUAD_TOP_LEFT] = spu_mul(topLeft, wInv); - result[QUAD_TOP_RIGHT] = spu_mul(spu_add(topLeft, dadx), wInv); - result[QUAD_BOTTOM_LEFT] = spu_mul(spu_add(topLeft, dady), wInv); - result[QUAD_BOTTOM_RIGHT] = spu_mul(spu_add(spu_add(topLeft, dadx), dady), wInv); - } - break; - case INTERP_POS: - case INTERP_NONE: - break; - default: - ASSERT(0); - } + return spu_splats(spu_extract(v, CHAN0)); } - -/** - * As above, but return 4 vectors in SOA format. - * XXX this will all be re-written someday. - */ -static INLINE void -eval_coeff_soa(uint slot, float x, float y, vector float w, vector float result[4]) +static INLINE vector float +splaty(vector float v) { - eval_coeff(slot, x, y, w, result); - _transpose_matrix4x4(result, result); + return spu_splats(spu_extract(v, CHAN1)); } +static INLINE vector float +splatz(vector float v) +{ + return spu_splats(spu_extract(v, CHAN2)); +} -/** Evalute coefficients to get Z for four pixels in a quad */ static INLINE vector float -eval_z(float x, float y) +splatw(vector float v) { - const uint slot = 0; - const float dzdx = spu_extract(setup.coef[slot].dadx, 2); - const float dzdy = spu_extract(setup.coef[slot].dady, 2); - const float topLeft = spu_extract(setup.coef[slot].a0, 2) + x * dzdx + y * dzdy; - const vector float topLeftv = spu_splats(topLeft); - const vector float derivs = (vector float) { 0.0, dzdx, dzdy, dzdx + dzdy }; - return spu_add(topLeftv, derivs); + return spu_splats(spu_extract(v, CHAN3)); } -/** Evalute coefficients to get W for four pixels in a quad */ -static INLINE vector float -eval_w(float x, float y) +/** + * Setup fragment shader inputs by evaluating triangle's vertex + * attribute coefficient info. + * \param x quad x pos + * \param y quad y pos + * \param fragZ returns quad Z values + * \param fragInputs returns fragment program inputs + * Note: this code could be incorporated into the fragment program + * itself to avoid the loop and switch. + */ +static void +eval_inputs(float x, float y, vector float *fragZ, vector float fragInputs[]) { - const uint slot = 0; - const float dwdx = spu_extract(setup.coef[slot].dadx, 3); - const float dwdy = spu_extract(setup.coef[slot].dady, 3); - const float topLeft = spu_extract(setup.coef[slot].a0, 3) + x * dwdx + y * dwdy; - const vector float topLeftv = spu_splats(topLeft); - const vector float derivs = (vector float) { 0.0, dwdx, dwdy, dwdx + dwdy }; - return spu_add(topLeftv, derivs); + static const vector float deltaX = (const vector float) {0, 1, 0, 1}; + static const vector float deltaY = (const vector float) {0, 0, 1, 1}; + + const uint posSlot = 0; + const vector float pos = setup.coef[posSlot].a0; + const vector float dposdx = setup.coef[posSlot].dadx; + const vector float dposdy = setup.coef[posSlot].dady; + const vector float fragX = spu_splats(x) + deltaX; + const vector float fragY = spu_splats(y) + deltaY; + vector float fragW, wInv; + uint i; + + *fragZ = splatz(pos) + fragX * splatz(dposdx) + fragY * splatz(dposdy); + fragW = splatw(pos) + fragX * splatw(dposdx) + fragY * splatw(dposdy); + wInv = spu_re(fragW); /* 1 / w */ + + /* loop over fragment program inputs */ + for (i = 0; i < spu.vertex_info.num_attribs; i++) { + uint attr = i + 1; + enum interp_mode interp = spu.vertex_info.attrib[attr].interp_mode; + + /* constant term */ + vector float a0 = setup.coef[attr].a0; + vector float r0 = splatx(a0); + vector float r1 = splaty(a0); + vector float r2 = splatz(a0); + vector float r3 = splatw(a0); + + if (interp == INTERP_LINEAR || interp == INTERP_PERSPECTIVE) { + /* linear term */ + vector float dadx = setup.coef[attr].dadx; + vector float dady = setup.coef[attr].dady; + /* Use SPU intrinsics here to get slightly better code. + * originally: r0 += fragX * splatx(dadx) + fragY * splatx(dady); + */ + r0 = spu_madd(fragX, splatx(dadx), spu_madd(fragY, splatx(dady), r0)); + r1 = spu_madd(fragX, splaty(dadx), spu_madd(fragY, splaty(dady), r1)); + r2 = spu_madd(fragX, splatz(dadx), spu_madd(fragY, splatz(dady), r2)); + r3 = spu_madd(fragX, splatw(dadx), spu_madd(fragY, splatw(dady), r3)); + if (interp == INTERP_PERSPECTIVE) { + /* perspective term */ + r0 *= wInv; + r1 *= wInv; + r2 *= wInv; + r3 *= wInv; + } + } + fragInputs[CHAN0] = r0; + fragInputs[CHAN1] = r1; + fragInputs[CHAN2] = r2; + fragInputs[CHAN3] = r3; + fragInputs += 4; + } } @@ -262,19 +265,11 @@ emit_quad( int x, int y, mask_t mask) * Run fragment shader, execute per-fragment ops, update fb/tile. */ vector float inputs[4*4], outputs[2*4]; - vector float fragZ = eval_z((float) x, (float) y); - vector float fragW = eval_w((float) x, (float) y); vector unsigned int kill_mask; + vector float fragZ; + + eval_inputs((float) x, (float) y, &fragZ, inputs); - /* setup inputs */ -#if 0 - eval_coeff_soa(1, (float) x, (float) y, fragW, inputs); -#else - uint i; - for (i = 0; i < spu.vertex_info.num_attribs; i++) { - eval_coeff_soa(i+1, (float) x, (float) y, fragW, inputs + i * 4); - } -#endif ASSERT(spu.fragment_program); ASSERT(spu.fragment_ops); diff --git a/src/gallium/drivers/cell/spu/spu_util.c b/src/gallium/drivers/cell/spu/spu_util.c index b8a0d4a265..af25dd3718 100644 --- a/src/gallium/drivers/cell/spu/spu_util.c +++ b/src/gallium/drivers/cell/spu/spu_util.c @@ -1,7 +1,7 @@ #include "cell/common.h" #include "pipe/p_shader_tokens.h" -#include "pipe/p_debug.h" +#include "util/u_debug.h" #include "tgsi/tgsi_parse.h" //#include "tgsi_build.h" #include "tgsi/tgsi_util.h" |