cell: untwiddle surface contents in flush_frontbuffer()

Don't make the shared software winsys rely on internal knowledge about
the cell driver's texture twiddling.

This is just a sketch and hasn't even been compile tested.
This commit is contained in:
Keith Whitwell 2010-03-09 14:03:41 +00:00
parent fe94a363e5
commit 65233674d3
4 changed files with 58 additions and 129 deletions

View file

@ -164,22 +164,6 @@ cell_destroy_screen( struct pipe_screen *screen )
FREE(screen);
}
/* This used to be overriden by the co-state tracker, but really needs
* to be active with sw_winsys.
*/
static void
cell_flush_frontbuffer(struct pipe_screen *_screen,
struct pipe_surface *surface,
void *context_private)
{
struct cell_screen *screen = cell_screen(_screen);
struct sw_winsys *winsys = screen->winsys;
struct cell_texture *texture = cell_texture(surface->texture);
assert(texture->dt);
if (texture->dt)
winsys->displaytarget_display(winsys, texture->dt, context_private);
}
/**

View file

@ -108,7 +108,7 @@ cell_displaytarget_layout(struct pipe_screen *screen,
ct->base.width0,
ct->base.height0,
16,
&ct->stride[0] );
&ct->dt_stride );
return ct->dt != NULL;
}
@ -125,21 +125,29 @@ cell_texture_create(struct pipe_screen *screen,
pipe_reference_init(&ct->base.reference, 1);
ct->base.screen = screen;
/* Create both a displaytarget (linear) and regular texture
* (twiddled). Convert twiddled->linear at flush_frontbuffer time.
*/
if (ct->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
PIPE_TEXTURE_USAGE_SCANOUT |
PIPE_TEXTURE_USAGE_SHARED)) {
if (!cell_displaytarget_layout(screen, ct))
goto fail;
}
else {
if (!cell_texture_layout(screen, ct))
goto fail;
}
if (!cell_texture_layout(screen, ct))
goto fail;
return &ct->base;
fail:
if (ct->dt) {
struct sw_winsys winsys = cell_screen(screen)->winsys;
winsys->displaytarget_destroy(winsys, ct->dt);
}
FREE(ct);
return NULL;
}
@ -151,20 +159,12 @@ cell_texture_destroy(struct pipe_texture *pt)
struct sw_winsys *winsys = screen->winsys;
struct cell_texture *ct = cell_texture(pt);
if (ct->mapped) {
if (ct->dt)
winsys->displaytarget_unmap(winsys, ct->dt);
ct->mapped = NULL;
}
if (ct->dt) {
/* display target */
winsys->displaytarget_destroy(winsys, ct->dt);
}
else {
/* regular texture */
align_free(ct->data);
}
align_free(ct->data);
FREE(ct);
}
@ -432,19 +432,9 @@ cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer)
assert(transfer->texture);
if (ct->mapped == NULL) {
if (ct->dt) {
struct sw_winsys *winsys = cell_screen(screen)->winsys;
ct->mapped = winsys->displaytarget_map(screen, ct->dt,
pipe_transfer_buffer_flags(transfer));
}
else {
ct->mapped = ct->data;
}
ct->mapped = ct->data;
}
if (ct->mapped == NULL)
return NULL;
/*
* Create a buffer of ordinary memory for the linear texture.
* This is the memory that the user will read/write.
@ -511,18 +501,51 @@ cell_transfer_unmap(struct pipe_screen *screen,
}
}
if (ct->dt) {
/* display target */
struct sw_winsys *winsys = cell_screen(screen)->winsys;
winsys->displaytarget_unmap(winsys, ct->dt);
}
align_free(ctrans->map);
ctrans->map = NULL;
}
/* This used to be overriden by the co-state tracker, but really needs
* to be active with sw_winsys.
*
* Contrasting with llvmpipe and softpipe, this is the only place
* where we use the ct->dt display target in any real sense.
*
* Basically just untwiddle our local data into the linear
* displaytarget.
*/
static void
cell_flush_frontbuffer(struct pipe_screen *_screen,
struct pipe_surface *surface,
void *context_private)
{
struct cell_screen *screen = cell_screen(_screen);
struct sw_winsys *winsys = screen->winsys;
struct cell_texture *ct = cell_texture(surface->texture);
if (!ct->dt)
return;
/* Need to untwiddle from our internal representation here:
*/
{
unsigned *map = winsys->displaytarget_map(winsys, ct->dt);
unsigned *src = (unsigned *)(ct->data + ct->level_offset[surface->level]);
untwiddle_image_uint(surface->width,
surface->height,
TILE_SIZE,
map,
ct->dt_stride,
src);
winsys->displaytarget_unmap(winsys, c->dt);
}
winsys->displaytarget_display(winsys, ct->dt, context_private);
}
void
@ -539,4 +562,6 @@ cell_init_screen_texture_funcs(struct pipe_screen *screen)
screen->transfer_map = cell_transfer_map;
screen->transfer_unmap = cell_transfer_unmap;
screen->flush_frontbuffer = cell_flush_frontbuffer;
}

View file

@ -48,6 +48,7 @@ struct cell_texture
* usage.
*/
struct sw_displaytarget *dt;
unsigned dt_stride;
/**
* Malloc'ed data for regular textures, or a mapping to dt above.

View file

@ -47,88 +47,7 @@
/**
* For Cell. Basically, rearrange the pixels/quads from this layout:
* +--+--+--+--+
* |p0|p1|p2|p3|....
* +--+--+--+--+
*
* to this layout:
* +--+--+
* |p0|p1|....
* +--+--+
* |p2|p3|
* +--+--+
*/
static void
twiddle_tile(const uint *tileIn, uint *tileOut)
{
int y, x;
for (y = 0; y < TILE_SIZE; y+=2) {
for (x = 0; x < TILE_SIZE; x+=2) {
int k = 4 * (y/2 * TILE_SIZE/2 + x/2);
tileOut[y * TILE_SIZE + (x + 0)] = tileIn[k];
tileOut[y * TILE_SIZE + (x + 1)] = tileIn[k+1];
tileOut[(y + 1) * TILE_SIZE + (x + 0)] = tileIn[k+2];
tileOut[(y + 1) * TILE_SIZE + (x + 1)] = tileIn[k+3];
}
}
}
/**
* Display a surface that's in a tiled configuration. That is, all the
* pixels for a TILE_SIZExTILE_SIZE block are contiguous in memory.
*/
static void
xm_displaytarget_display(struct sw_winsys *ws,
struct sw_displaytarget *dt,
void *winsys_drawable)
{
struct xmesa_buffer *xm_buffer = (struct xm_drawable *)winsys_drawable;
XImage *ximage;
struct xm_buffer *xm_buf = xm_buffer(
cell_texture(surf->texture)->buffer);
const uint tilesPerRow = (surf->width + TILE_SIZE - 1) / TILE_SIZE;
uint x, y;
ximage = b->tempImage;
/* check that the XImage has been previously initialized */
assert(ximage->format);
assert(ximage->bitmap_unit);
/* update XImage's fields */
ximage->width = TILE_SIZE;
ximage->height = TILE_SIZE;
ximage->bytes_per_line = TILE_SIZE * 4;
for (y = 0; y < surf->height; y += TILE_SIZE) {
for (x = 0; x < surf->width; x += TILE_SIZE) {
uint tmpTile[TILE_SIZE * TILE_SIZE];
int tx = x / TILE_SIZE;
int ty = y / TILE_SIZE;
int offset = ty * tilesPerRow + tx;
int w = TILE_SIZE;
int h = TILE_SIZE;
if (y + h > surf->height)
h = surf->height - y;
if (x + w > surf->width)
w = surf->width - x;
/* offset in pixels */
offset *= TILE_SIZE * TILE_SIZE;
/* twiddle from ximage buffer to temp tile */
twiddle_tile((uint *) xm_buf->data + offset, tmpTile);
/* display temp tile data */
ximage->data = (char *) tmpTile;
XPutImage(b->xm_visual->display, b->drawable, b->gc,
ximage, 0, 0, x, y, w, h);
}
}
}