#define CELL_CMD_CLEAR_TILES 3
#define CELL_CMD_TRIANGLE 4
#define CELL_CMD_FINISH 5
+#define CELL_CMD_RENDER 6
/**
} ALIGN16_ATTRIB;
+struct cell_command_render
+{
+ uint prim_type;
+ uint num_verts;
+ float xmin, ymin, xmax, ymax;
+ void *vertex_data;
+} ALIGN16_ATTRIB;
+
+
/** XXX unions don't seem to work */
struct cell_command
{
struct cell_command_framebuffer fb;
struct cell_command_clear_tiles clear;
struct cell_command_triangle tri;
+ struct cell_command_render render;
} ALIGN16_ATTRIB;
} ALIGN16_ATTRIB;
+/** Temporary */
+#define CELL_MAX_VERTS 48
+#define CELL_MAX_ATTRIBS 2
+struct cell_prim_buffer
+{
+ float vertex[CELL_MAX_VERTS][CELL_MAX_ATTRIBS][4] ALIGN16_ATTRIB;
+ float xmin, ymin, xmax, ymax;
+ uint num_verts;
+} ALIGN16_ATTRIB;
+
#endif /* CELL_COMMON_H */
{
struct cell_context *cell;
- cell = CALLOC_STRUCT(cell_context);
+ /* some fields need to be 16-byte aligned, so align the whole object */
+ cell = (struct cell_context*) align_malloc(sizeof(struct cell_context), 16);
if (!cell)
return NULL;
+ memset(cell, 0, sizeof(*cell));
+
cell->winsys = cws;
cell->pipe.winsys = winsys;
cell->pipe.destroy = cell_destroy_context;
#include "pipe/p_defines.h"
#include "pipe/draw/draw_vertex.h"
#include "cell_winsys.h"
+#include "pipe/cell/common.h"
struct cell_vertex_shader_state
uint num_spus;
-
+ struct cell_prim_buffer prim_buffer;
};
#include "cell_context.h"
#include "cell_flush.h"
#include "cell_spu.h"
+#include "cell_render.h"
void
printf("%s\n", __FUNCTION__);
+ cell_flush_prim_buffer(cell);
+
/* Send CMD_FINISH to all SPUs */
for (i = 0; i < cell->num_spus; i++) {
send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_FINISH);
#include "cell_context.h"
#include "cell_render.h"
+#include "cell_spu.h"
#include "pipe/p_util.h"
#include "pipe/draw/draw_private.h"
}
+/** Write a vertex into the prim buffer */
+static void
+save_vertex(struct cell_prim_buffer *buf, uint pos,
+ const struct vertex_header *vert)
+{
+ uint attr, j;
+
+ for (attr = 0; attr < 2; attr++) {
+ for (j = 0; j < 4; j++) {
+ buf->vertex[pos][attr][j] = vert->data[attr][j];
+ }
+ }
+
+ /* update bounding box */
+ if (vert->data[0][0] < buf->xmin)
+ buf->xmin = vert->data[0][0];
+ if (vert->data[0][0] > buf->xmax)
+ buf->xmax = vert->data[0][0];
+ if (vert->data[0][1] < buf->ymin)
+ buf->ymin = vert->data[0][1];
+ if (vert->data[0][1] > buf->ymax)
+ buf->ymax = vert->data[0][1];
+}
+
+
static void
render_tri(struct draw_stage *stage, struct prim_header *prim)
{
+ struct render_stage *rs = render_stage(stage);
+ struct cell_context *cell = rs->cell;
+ struct cell_prim_buffer *buf = &cell->prim_buffer;
+ uint i;
+
printf("Cell render tri\n");
+
+ if (buf->num_verts + 3 > CELL_MAX_VERTS) {
+ cell_flush_prim_buffer(cell);
+ }
+
+ i = buf->num_verts;
+ assert(i+2 <= CELL_MAX_VERTS);
+ save_vertex(buf, i+0, prim->v[0]);
+ save_vertex(buf, i+1, prim->v[1]);
+ save_vertex(buf, i+2, prim->v[2]);
+ buf->num_verts += 3;
}
+/**
+ * Send the a RENDER command to all SPUs to have them render the prims
+ * in the current prim_buffer.
+ */
+void
+cell_flush_prim_buffer(struct cell_context *cell)
+{
+ uint i;
+
+ if (cell->prim_buffer.num_verts == 0)
+ return;
+
+ printf("*** Flushing prim buffer\n");
+ for (i = 0; i < cell->num_spus; i++) {
+ struct cell_command_render *render = &cell_global.command[i].render;
+ render->prim_type = PIPE_PRIM_TRIANGLES;
+ render->num_verts = cell->prim_buffer.num_verts;
+ render->xmin = cell->prim_buffer.xmin;
+ render->ymin = cell->prim_buffer.ymin;
+ render->xmax = cell->prim_buffer.xmax;
+ render->ymax = cell->prim_buffer.ymax;
+ render->vertex_data = &cell->prim_buffer.vertex;
+ ASSERT_ALIGN16(render->vertex_data);
+ send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_RENDER);
+ }
+
+ cell->prim_buffer.num_verts = 0;
+}
+
+
+
static void render_destroy( struct draw_stage *stage )
{
FREE( stage );
struct cell_context;
struct draw_stage;
+extern void
+cell_flush_prim_buffer(struct cell_context *cell);
+
extern struct draw_stage *cell_draw_render_stage( struct cell_context *cell );
#endif /* CELL_RENDER_H */
if (!ps->map)
pipe_surface_map(ps);
+ if (pf_get_size(ps->format) != 4) {
+ printf("Cell: Skipping non 32bpp clear_surface\n");
+ return;
+ }
+
for (i = 0; i < cell->num_spus; i++) {
struct cell_command_framebuffer *fb = &cell_global.command[i].fb;
+ printf("%s %u start = 0x%x\n", __FUNCTION__, i, ps->map);
fb->start = ps->map;
fb->width = ps->width;
fb->height = ps->height;
send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_CLEAR_TILES);
}
-#if 1
+#if 0
/* XXX Draw a test triangle over the cleared surface */
for (i = 0; i < cell->num_spus; i++) {
/* Same triangle data for all SPUs */
#include "main.h"
#include "tri.h"
#include "pipe/cell/common.h"
+#include "pipe/p_defines.h"
/*
helpful headers:
struct framebuffer fb;
+uint tile[TILE_SIZE][TILE_SIZE] ALIGN16_ATTRIB;
+
int DefaultTag;
void
-get_tile(const struct framebuffer *fb, uint tx, uint ty, uint *tile)
+get_tile(const struct framebuffer *fb, uint tx, uint ty, uint *tile,
+ int tag)
{
uint offset = ty * fb->width_tiles + tx;
uint bytesPerTile = TILE_SIZE * TILE_SIZE * 4;
ubyte *src = (ubyte *) fb->start + offset * bytesPerTile;
- int tag = DefaultTag;
assert(tx < fb->width_tiles);
assert(ty < fb->height_tiles);
}
void
-put_tile(const struct framebuffer *fb, uint tx, uint ty, const uint *tile)
+put_tile(const struct framebuffer *fb, uint tx, uint ty, const uint *tile,
+ int tag)
{
uint offset = ty * fb->width_tiles + tx;
uint bytesPerTile = TILE_SIZE * TILE_SIZE * 4;
ubyte *dst = (ubyte *) fb->start + offset * bytesPerTile;
- int tag = DefaultTag;
assert(tx < fb->width_tiles);
assert(ty < fb->height_tiles);
tile, (unsigned int) dst, bytesPerTile);
*/
mfc_put((void *) tile, /* src in local memory */
- (unsigned int) dst, /* dst in main mory */
+ (unsigned int) dst, /* dst in main memory */
bytesPerTile,
tag,
0, /* tid */
for (i = 0; i < TILE_SIZE * TILE_SIZE; i++)
tile[i] = clear->value;
+ /*
printf("SPU: %s num=%d w=%d h=%d\n",
__FUNCTION__, num_tiles, fb.width_tiles, fb.height_tiles);
+ */
+
for (i = init.id; i < num_tiles; i += init.num_spus) {
uint tx = i % fb.width_tiles;
uint ty = i / fb.width_tiles;
- put_tile(&fb, tx, ty, tile);
+ put_tile(&fb, tx, ty, tile, DefaultTag);
/* XXX we don't want this here, but it fixes bad tile results */
wait_on_mask(1 << DefaultTag);
}
+
}
+static void
+render(const struct cell_command_render *render)
+{
+ const uint num_tiles = fb.width_tiles * fb.height_tiles;
+ struct cell_prim_buffer prim_buffer ALIGN16_ATTRIB;
+ int tag = DefaultTag;
+ uint i, j;
+
+ /*
+ printf("SPU %u: RENDER buffer dst=%p src=%p size=%d\n",
+ init.id,
+ &prim_buffer, render->vertex_data, (int)sizeof(prim_buffer));
+ */
+
+ ASSERT_ALIGN16(render->vertex_data);
+ ASSERT_ALIGN16(&prim_buffer);
+
+ /* get vertex data from main memory */
+ mfc_get(&prim_buffer, /* dest */
+ (unsigned int) render->vertex_data, /* src */
+ sizeof(prim_buffer), /* bytes */
+ tag,
+ 0, /* tid */
+ 0 /* rid */);
+ wait_on_mask( 1 << tag ); /* XXX temporary */
+
+ /* loop over tiles */
+ for (i = init.id; i < num_tiles; i += init.num_spus) {
+ uint tx = i % fb.width_tiles;
+ uint ty = i / fb.width_tiles;
+
+ get_tile(&fb, tx, ty, (uint *) tile, DefaultTag);
+ wait_on_mask(1 << DefaultTag); /* XXX temporary */
+
+ assert(render->prim_type == PIPE_PRIM_TRIANGLES);
+
+ /* loop over tris */
+ for (j = 0; j < render->num_verts; j += 3) {
+ struct prim_header prim;
+
+ /*
+ printf(" %u: Triangle %g,%g %g,%g %g,%g\n",
+ init.id,
+ prim_buffer.vertex[j*3+0][0][0],
+ prim_buffer.vertex[j*3+0][0][1],
+ prim_buffer.vertex[j*3+1][0][0],
+ prim_buffer.vertex[j*3+1][0][1],
+ prim_buffer.vertex[j*3+2][0][0],
+ prim_buffer.vertex[j*3+2][0][1]);
+ */
+
+ /* pos */
+ COPY_4V(prim.v[0].data[0], prim_buffer.vertex[j+0][0]);
+ COPY_4V(prim.v[1].data[0], prim_buffer.vertex[j+1][0]);
+ COPY_4V(prim.v[2].data[0], prim_buffer.vertex[j+2][0]);
+
+ /* color */
+ COPY_4V(prim.v[0].data[1], prim_buffer.vertex[j+0][1]);
+ COPY_4V(prim.v[1].data[1], prim_buffer.vertex[j+1][1]);
+ COPY_4V(prim.v[2].data[1], prim_buffer.vertex[j+2][1]);
+
+ draw_triangle(&prim, tx, ty);
+ }
+
+ put_tile(&fb, tx, ty, (uint *) tile, DefaultTag);
+ wait_on_mask(1 << DefaultTag); /* XXX temp */
+ }
+}
+
+
/**
* Temporary/simple main loop for SPEs: Get a command, execute it, repeat.
*/
printf("SPU %u: TRIANGLE\n", init.id);
triangle(&cmd.tri);
break;
+ case CELL_CMD_RENDER:
+ printf("SPU %u: RENDER %u verts, prim %u\n",
+ init.id, cmd.render.num_verts, cmd.render.prim_type);
+ render(&cmd.render);
+ break;
+
case CELL_CMD_FINISH:
printf("SPU %u: FINISH\n", init.id);
/* wait for all outstanding DMAs to finish */
extern volatile struct cell_init_info init;
struct framebuffer {
- void *start;
- uint width, height;
+ void *start; /**< addr of surface in main memory */
+ uint width, height; /**< size in pixels */
uint width_tiles, height_tiles; /**< width and height in tiles */
};
+/* XXX Collect these globals in a struct: */
+
extern struct framebuffer fb;
+extern uint tile[TILE_SIZE][TILE_SIZE] ALIGN16_ATTRIB;
extern int DefaultTag;
wait_on_mask(unsigned tag);
void
-get_tile(const struct framebuffer *fb, uint tx, uint ty, uint *tile);
+get_tile(const struct framebuffer *fb, uint tx, uint ty, uint *tile,
+ int tag);
void
-put_tile(const struct framebuffer *fb, uint tx, uint ty, const uint *tile);
+put_tile(const struct framebuffer *fb, uint tx, uint ty, const uint *tile,
+ int tag);
#endif /* MAIN_H */
static int cliprect_minx, cliprect_maxx, cliprect_miny, cliprect_maxy;
-static uint tile[TILE_SIZE][TILE_SIZE] ALIGN16_ATTRIB;
-
#endif
cliprect_maxx = (tx + 1) * TILE_SIZE;
cliprect_maxy = (ty + 1) * TILE_SIZE;
- get_tile(&fb, tx, ty, (uint *) tile);
+ get_tile(&fb, tx, ty, (uint *) tile, DefaultTag);
wait_on_mask(1 << DefaultTag);
setup_tri(tri);
- put_tile(&fb, tx, ty, (uint *) tile);
+ put_tile(&fb, tx, ty, (uint *) tile, DefaultTag);
wait_on_mask(1 << DefaultTag);
}
+
+
+void
+tri_draw(struct prim_header *tri, uint tx, uint ty)
+{
+ /* set clipping bounds to tile bounds */
+ cliprect_minx = tx * TILE_SIZE;
+ cliprect_miny = ty * TILE_SIZE;
+ cliprect_maxx = (tx + 1) * TILE_SIZE;
+ cliprect_maxy = (ty + 1) * TILE_SIZE;
+
+ setup_tri(tri);
+}
+
+
draw_triangle(struct prim_header *tri, uint tx, uint ty);
+extern void
+tri_draw(struct prim_header *tri, uint tx, uint ty);
+
+
#endif /* TRI_H */
#ifdef GALLIUM_CELL
#include "pipe/cell/ppu/cell_context.h"
#include "pipe/cell/ppu/cell_winsys.h"
+#else
+#define TILE_SIZE 32 /* avoid compilation errors */
#endif
+
#include "xm_winsys_aub.h"
{
XImage *ximage = b->tempImage;
struct xm_buffer *xm_buf = xm_bo(surf->buffer);
- const int TILE_SIZE = 32;
const uint tilesPerRow = (surf->width + TILE_SIZE - 1) / TILE_SIZE;
uint x, y;
int tx = x / TILE_SIZE;
int ty = y / TILE_SIZE;
int offset = ty * tilesPerRow + tx;
+
offset *= 4 * TILE_SIZE * TILE_SIZE;
ximage->data = (char *) xm_buf->data + offset;
surf->cpp = pf_get_size(format);
surf->pitch = round_up(width, alignment / surf->cpp);
+#ifdef GALLIUM_CELL /* XXX a bit of a hack */
+ height = round_up(height, TILE_SIZE);
+#endif
+
assert(!surf->buffer);
surf->buffer = winsys->buffer_create(winsys, alignment, 0, 0);
if(!surf->buffer)