summaryrefslogtreecommitdiff
path: root/src/mesa/pipe/cell/ppu
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2008-02-09 16:15:14 +1100
committerBen Skeggs <skeggsb@gmail.com>2008-02-09 16:15:14 +1100
commitfb2760c5a64ada7b0f0a9635e7865b415a8aa286 (patch)
treec70e82ce993cfbbb789860516d667a6a44528668 /src/mesa/pipe/cell/ppu
parentae905056d4feb5a39d956a38ab377f4d78bf4065 (diff)
parent479b5e9b5d9e0e387332c6fbeaffffa7612a0c52 (diff)
Merge branch 'upstream-gallium-0.1' into darktama-gallium-0.1
Diffstat (limited to 'src/mesa/pipe/cell/ppu')
-rw-r--r--src/mesa/pipe/cell/ppu/Makefile1
-rw-r--r--src/mesa/pipe/cell/ppu/cell_batch.c144
-rw-r--r--src/mesa/pipe/cell/ppu/cell_batch.h9
-rw-r--r--src/mesa/pipe/cell/ppu/cell_clear.c34
-rw-r--r--src/mesa/pipe/cell/ppu/cell_context.c21
-rw-r--r--src/mesa/pipe/cell/ppu/cell_context.h20
-rw-r--r--src/mesa/pipe/cell/ppu/cell_flush.c5
-rw-r--r--src/mesa/pipe/cell/ppu/cell_spu.c4
-rw-r--r--src/mesa/pipe/cell/ppu/cell_state_blend.c16
-rw-r--r--src/mesa/pipe/cell/ppu/cell_state_emit.c53
-rw-r--r--src/mesa/pipe/cell/ppu/cell_state_fs.c4
-rw-r--r--src/mesa/pipe/cell/ppu/cell_state_sampler.c14
-rw-r--r--src/mesa/pipe/cell/ppu/cell_texture.c119
-rw-r--r--src/mesa/pipe/cell/ppu/cell_texture.h11
-rw-r--r--src/mesa/pipe/cell/ppu/cell_vbuf.c136
-rw-r--r--src/mesa/pipe/cell/ppu/cell_vertex_shader.c120
16 files changed, 528 insertions, 183 deletions
diff --git a/src/mesa/pipe/cell/ppu/Makefile b/src/mesa/pipe/cell/ppu/Makefile
index e7f2562da7..50060f5cd3 100644
--- a/src/mesa/pipe/cell/ppu/Makefile
+++ b/src/mesa/pipe/cell/ppu/Makefile
@@ -34,6 +34,7 @@ SOURCES = \
cell_surface.c \
cell_texture.c \
cell_vbuf.c \
+ cell_vertex_shader.c \
cell_winsys.c
diff --git a/src/mesa/pipe/cell/ppu/cell_batch.c b/src/mesa/pipe/cell/ppu/cell_batch.c
index c894ef8608..f45e5f25b6 100644
--- a/src/mesa/pipe/cell/ppu/cell_batch.c
+++ b/src/mesa/pipe/cell/ppu/cell_batch.c
@@ -31,12 +31,55 @@
#include "cell_spu.h"
+
+uint
+cell_get_empty_buffer(struct cell_context *cell)
+{
+ uint buf = 0, tries = 0;
+
+ /* Find a buffer that's marked as free by all SPUs */
+ while (1) {
+ uint spu, num_free = 0;
+
+ for (spu = 0; spu < cell->num_spus; spu++) {
+ if (cell->buffer_status[spu][buf][0] == CELL_BUFFER_STATUS_FREE) {
+ num_free++;
+
+ if (num_free == cell->num_spus) {
+ /* found a free buffer, now mark status as used */
+ for (spu = 0; spu < cell->num_spus; spu++) {
+ cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_USED;
+ }
+ /*
+ printf("PPU: ALLOC BUFFER %u\n", buf);
+ */
+ return buf;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ /* try next buf */
+ buf = (buf + 1) % CELL_NUM_BUFFERS;
+
+ tries++;
+ if (tries == 100) {
+ /*
+ printf("PPU WAITING for buffer...\n");
+ */
+ }
+ }
+}
+
+
void
cell_batch_flush(struct cell_context *cell)
{
static boolean flushing = FALSE;
uint batch = cell->cur_batch;
- const uint size = cell->batch_buffer_size[batch];
+ const uint size = cell->buffer_size[batch];
uint spu, cmd_word;
assert(!flushing);
@@ -46,7 +89,7 @@ cell_batch_flush(struct cell_context *cell)
flushing = TRUE;
- assert(batch < CELL_NUM_BATCH_BUFFERS);
+ assert(batch < CELL_NUM_BUFFERS);
/*
printf("cell_batch_dispatch: buf %u at %p, size %u\n",
@@ -68,28 +111,9 @@ cell_batch_flush(struct cell_context *cell)
* array indicating that the PPU can re-use the buffer.
*/
+ batch = cell_get_empty_buffer(cell);
- /* Find a buffer that's marked as free by all SPUs */
- while (1) {
- uint num_free = 0;
-
- batch = (batch + 1) % CELL_NUM_BATCH_BUFFERS;
-
- for (spu = 0; spu < cell->num_spus; spu++) {
- if (cell->buffer_status[spu][batch][0] == CELL_BUFFER_STATUS_FREE)
- num_free++;
- }
-
- if (num_free == cell->num_spus) {
- /* found a free buffer, now mark status as used */
- for (spu = 0; spu < cell->num_spus; spu++) {
- cell->buffer_status[spu][batch][0] = CELL_BUFFER_STATUS_USED;
- }
- break;
- }
- }
-
- cell->batch_buffer_size[batch] = 0; /* empty */
+ cell->buffer_size[batch] = 0; /* empty */
cell->cur_batch = batch;
flushing = FALSE;
@@ -99,61 +123,95 @@ cell_batch_flush(struct cell_context *cell)
uint
cell_batch_free_space(const struct cell_context *cell)
{
- uint free = CELL_BATCH_BUFFER_SIZE
- - cell->batch_buffer_size[cell->cur_batch];
+ uint free = CELL_BUFFER_SIZE - cell->buffer_size[cell->cur_batch];
return free;
}
/**
- * \param cmd command to append
- * \param length command size in bytes
+ * Append data to current batch.
*/
void
-cell_batch_append(struct cell_context *cell, const void *cmd, uint length)
+cell_batch_append(struct cell_context *cell, const void *data, uint bytes)
{
uint size;
- assert(length % 4 == 0);
- assert(cell->cur_batch >= 0);
+ ASSERT(bytes % 8 == 0);
+ ASSERT(bytes <= CELL_BUFFER_SIZE);
+ ASSERT(cell->cur_batch >= 0);
+
+#ifdef ASSERT
+ {
+ uint spu;
+ for (spu = 0; spu < cell->num_spus; spu++) {
+ ASSERT(cell->buffer_status[spu][cell->cur_batch][0]
+ == CELL_BUFFER_STATUS_USED);
+ }
+ }
+#endif
- size = cell->batch_buffer_size[cell->cur_batch];
+ size = cell->buffer_size[cell->cur_batch];
- if (size + length > CELL_BATCH_BUFFER_SIZE) {
+ if (size + bytes > CELL_BUFFER_SIZE) {
cell_batch_flush(cell);
size = 0;
}
- assert(size + length <= CELL_BATCH_BUFFER_SIZE);
+ ASSERT(size + bytes <= CELL_BUFFER_SIZE);
- memcpy(cell->batch_buffer[cell->cur_batch] + size, cmd, length);
+ memcpy(cell->buffer[cell->cur_batch] + size, data, bytes);
- cell->batch_buffer_size[cell->cur_batch] = size + length;
+ cell->buffer_size[cell->cur_batch] = size + bytes;
}
void *
cell_batch_alloc(struct cell_context *cell, uint bytes)
{
+ return cell_batch_alloc_aligned(cell, bytes, 1);
+}
+
+
+void *
+cell_batch_alloc_aligned(struct cell_context *cell, uint bytes,
+ uint alignment)
+{
void *pos;
- uint size;
+ uint size, padbytes;
- ASSERT(bytes % 4 == 0);
+ ASSERT(bytes % 8 == 0);
+ ASSERT(bytes <= CELL_BUFFER_SIZE);
+ ASSERT(alignment > 0);
+ ASSERT(cell->cur_batch >= 0);
- assert(cell->cur_batch >= 0);
+#ifdef ASSERT
+ {
+ uint spu;
+ for (spu = 0; spu < cell->num_spus; spu++) {
+ ASSERT(cell->buffer_status[spu][cell->cur_batch][0]
+ == CELL_BUFFER_STATUS_USED);
+ }
+ }
+#endif
- size = cell->batch_buffer_size[cell->cur_batch];
+ size = cell->buffer_size[cell->cur_batch];
- if (size + bytes > CELL_BATCH_BUFFER_SIZE) {
+ padbytes = (alignment - (size % alignment)) % alignment;
+
+ if (padbytes + size + bytes > CELL_BUFFER_SIZE) {
cell_batch_flush(cell);
size = 0;
}
+ else {
+ size += padbytes;
+ }
- assert(size + bytes <= CELL_BATCH_BUFFER_SIZE);
+ ASSERT(size % alignment == 0);
+ ASSERT(size + bytes <= CELL_BUFFER_SIZE);
- pos = (void *) (cell->batch_buffer[cell->cur_batch] + size);
+ pos = (void *) (cell->buffer[cell->cur_batch] + size);
- cell->batch_buffer_size[cell->cur_batch] = size + bytes;
+ cell->buffer_size[cell->cur_batch] = size + bytes;
return pos;
}
diff --git a/src/mesa/pipe/cell/ppu/cell_batch.h b/src/mesa/pipe/cell/ppu/cell_batch.h
index c4ba7feb3d..a6eee0a8b1 100644
--- a/src/mesa/pipe/cell/ppu/cell_batch.h
+++ b/src/mesa/pipe/cell/ppu/cell_batch.h
@@ -35,6 +35,9 @@
struct cell_context;
+extern uint
+cell_get_empty_buffer(struct cell_context *cell);
+
extern void
cell_batch_flush(struct cell_context *cell);
@@ -42,10 +45,14 @@ extern uint
cell_batch_free_space(const struct cell_context *cell);
extern void
-cell_batch_append(struct cell_context *cell, const void *cmd, uint length);
+cell_batch_append(struct cell_context *cell, const void *data, uint bytes);
extern void *
cell_batch_alloc(struct cell_context *cell, uint bytes);
+extern void *
+cell_batch_alloc_aligned(struct cell_context *cell, uint bytes,
+ uint alignment);
+
#endif /* CELL_BATCH_H */
diff --git a/src/mesa/pipe/cell/ppu/cell_clear.c b/src/mesa/pipe/cell/ppu/cell_clear.c
index e01640b994..07b908eec5 100644
--- a/src/mesa/pipe/cell/ppu/cell_clear.c
+++ b/src/mesa/pipe/cell/ppu/cell_clear.c
@@ -48,9 +48,12 @@ cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps,
unsigned clearValue)
{
struct cell_context *cell = cell_context(pipe);
- /*uint i;*/
uint surfIndex;
+ if (cell->dirty)
+ cell_update_derived(cell);
+
+
if (!cell->cbuf_map[0])
cell->cbuf_map[0] = pipe_surface_map(ps);
@@ -61,29 +64,7 @@ cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps,
surfIndex = 0;
}
-#if 0
- for (i = 0; i < cell->num_spus; i++) {
-#if 1
- uint clr = clearValue;
- if (surfIndex == 0) {
- /* XXX debug: clear color varied per-SPU to visualize tiles */
- if ((clr & 0xff) == 0)
- clr |= 64 + i * 8;
- if ((clr & 0xff00) == 0)
- clr |= (64 + i * 8) << 8;
- if ((clr & 0xff0000) == 0)
- clr |= (64 + i * 8) << 16;
- if ((clr & 0xff000000) == 0)
- clr |= (64 + i * 8) << 24;
- }
- cell_global.command[i].clear.value = clr;
-#else
- cell_global.command[i].clear.value = clearValue;
-#endif
- cell_global.command[i].clear.surface = surfIndex;
- send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_CLEAR_SURFACE);
- }
-#else
+
{
struct cell_command_clear_surface *clr
= (struct cell_command_clear_surface *)
@@ -92,9 +73,4 @@ cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps,
clr->surface = surfIndex;
clr->value = clearValue;
}
-#endif
-
- /* XXX temporary */
- cell_flush(&cell->pipe, 0x0);
-
}
diff --git a/src/mesa/pipe/cell/ppu/cell_context.c b/src/mesa/pipe/cell/ppu/cell_context.c
index 8cb0c48f40..bbe1fd7a11 100644
--- a/src/mesa/pipe/cell/ppu/cell_context.c
+++ b/src/mesa/pipe/cell/ppu/cell_context.c
@@ -39,6 +39,7 @@
#include "pipe/p_winsys.h"
#include "pipe/cell/common.h"
#include "pipe/draw/draw_context.h"
+#include "pipe/draw/draw_private.h"
#include "cell_clear.h"
#include "cell_context.h"
#include "cell_draw_arrays.h"
@@ -156,6 +157,19 @@ cell_destroy_context( struct pipe_context *pipe )
}
+static struct draw_context *
+cell_draw_create(struct cell_context *cell)
+{
+ struct draw_context *draw = draw_create();
+
+ if (getenv("GALLIUM_CELL_VS")) {
+ /* plug in SPU-based vertex transformation code */
+ draw->shader_queue_flush = cell_vertex_shader_queue_flush;
+ draw->driver_private = cell;
+ }
+
+ return draw;
+}
struct pipe_context *
@@ -242,7 +256,7 @@ cell_create_context(struct pipe_winsys *winsys, struct cell_winsys *cws)
cell_init_surface_functions(cell);
- cell->draw = draw_create();
+ cell->draw = cell_draw_create(cell);
cell_init_vbuf(cell);
draw_set_rasterize_stage(cell->draw, cell->vbuf);
@@ -254,8 +268,9 @@ cell_create_context(struct pipe_winsys *winsys, struct cell_winsys *cws)
cell_start_spus(cell);
- for (buf = 0; buf < CELL_NUM_BATCH_BUFFERS; buf++) {
- cell->batch_buffer_size[buf] = 0;
+ /* init command, vertex/index buffer info */
+ for (buf = 0; buf < CELL_NUM_BUFFERS; buf++) {
+ cell->buffer_size[buf] = 0;
/* init batch buffer status values,
* mark 0th buffer as used, rest as free.
diff --git a/src/mesa/pipe/cell/ppu/cell_context.h b/src/mesa/pipe/cell/ppu/cell_context.h
index 3bd88bfd5b..3b63419b5e 100644
--- a/src/mesa/pipe/cell/ppu/cell_context.h
+++ b/src/mesa/pipe/cell/ppu/cell_context.h
@@ -38,9 +38,6 @@
#include "pipe/cell/common.h"
-#define CELL_MAX_SPUS 6
-
-
struct cell_vbuf_render;
struct cell_vertex_shader_state
@@ -76,7 +73,7 @@ struct cell_context
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
- struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
+ struct cell_texture *texture[PIPE_MAX_SAMPLERS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_ATTRIB_MAX];
struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX];
@@ -84,6 +81,9 @@ struct cell_context
ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS];
ubyte *zsbuf_map;
+ struct pipe_surface *tex_surf;
+ uint *tex_map;
+
uint dirty;
/** The primitive drawing context */
@@ -102,12 +102,14 @@ struct cell_context
uint num_spus;
- uint batch_buffer_size[CELL_NUM_BATCH_BUFFERS];
- ubyte batch_buffer[CELL_NUM_BATCH_BUFFERS][CELL_BATCH_BUFFER_SIZE] ALIGN16_ATTRIB;
- int cur_batch; /**< which batch buffer is being filled */
+ /** Buffers for command batches, vertex/index data */
+ uint buffer_size[CELL_NUM_BUFFERS];
+ ubyte buffer[CELL_NUM_BUFFERS][CELL_BUFFER_SIZE] ALIGN16_ATTRIB;
+
+ int cur_batch; /**< which buffer is being filled w/ commands */
/** [4] to ensure 16-byte alignment for each status word */
- uint buffer_status[CELL_MAX_SPUS][CELL_NUM_BATCH_BUFFERS][4] ALIGN16_ATTRIB;
+ uint buffer_status[CELL_MAX_SPUS][CELL_NUM_BUFFERS][4] ALIGN16_ATTRIB;
};
@@ -124,6 +126,8 @@ cell_context(struct pipe_context *pipe)
extern struct pipe_context *
cell_create_context(struct pipe_winsys *ws, struct cell_winsys *cws);
+extern void
+cell_vertex_shader_queue_flush(struct draw_context *draw);
diff --git a/src/mesa/pipe/cell/ppu/cell_flush.c b/src/mesa/pipe/cell/ppu/cell_flush.c
index b98bb566b1..f62bc4650c 100644
--- a/src/mesa/pipe/cell/ppu/cell_flush.c
+++ b/src/mesa/pipe/cell/ppu/cell_flush.c
@@ -39,6 +39,9 @@ cell_flush(struct pipe_context *pipe, unsigned flags)
{
struct cell_context *cell = cell_context(pipe);
+ if (flags & PIPE_FLUSH_SWAPBUFFERS)
+ flags |= PIPE_FLUSH_WAIT;
+
draw_flush( cell->draw );
cell_flush_int(pipe, flags);
}
@@ -56,7 +59,7 @@ cell_flush_int(struct pipe_context *pipe, unsigned flags)
flushing = TRUE;
if (flags & PIPE_FLUSH_WAIT) {
- uint *cmd = (uint *) cell_batch_alloc(cell, sizeof(uint));
+ uint64_t *cmd = (uint64_t *) cell_batch_alloc(cell, sizeof(uint64_t));
*cmd = CELL_CMD_FINISH;
}
diff --git a/src/mesa/pipe/cell/ppu/cell_spu.c b/src/mesa/pipe/cell/ppu/cell_spu.c
index 4627bc8d1f..7c83a47e57 100644
--- a/src/mesa/pipe/cell/ppu/cell_spu.c
+++ b/src/mesa/pipe/cell/ppu/cell_spu.c
@@ -111,8 +111,8 @@ cell_start_spus(struct cell_context *cell)
cell_global.inits[i].id = i;
cell_global.inits[i].num_spus = cell->num_spus;
cell_global.inits[i].cmd = &cell_global.command[i];
- for (j = 0; j < CELL_NUM_BATCH_BUFFERS; j++) {
- cell_global.inits[i].batch_buffers[j] = cell->batch_buffer[j];
+ for (j = 0; j < CELL_NUM_BUFFERS; j++) {
+ cell_global.inits[i].buffers[j] = cell->buffer[j];
}
cell_global.inits[i].buffer_status = &cell->buffer_status[0][0][0];
diff --git a/src/mesa/pipe/cell/ppu/cell_state_blend.c b/src/mesa/pipe/cell/ppu/cell_state_blend.c
index 34ae0128ea..4fc60548c8 100644
--- a/src/mesa/pipe/cell/ppu/cell_state_blend.c
+++ b/src/mesa/pipe/cell/ppu/cell_state_blend.c
@@ -29,6 +29,7 @@
*/
#include "pipe/p_util.h"
+#include "pipe/draw/draw_context.h"
#include "cell_context.h"
#include "cell_state.h"
@@ -38,9 +39,7 @@ void *
cell_create_blend_state(struct pipe_context *pipe,
const struct pipe_blend_state *blend)
{
- struct pipe_blend_state *state = MALLOC(sizeof(struct pipe_blend_state));
- memcpy(state, blend, sizeof(struct pipe_blend_state));
- return state;
+ return mem_dup(blend, sizeof(*blend));
}
@@ -49,6 +48,8 @@ cell_bind_blend_state(struct pipe_context *pipe, void *blend)
{
struct cell_context *cell = cell_context(pipe);
+ draw_flush(cell->draw);
+
cell->blend = (const struct pipe_blend_state *)blend;
cell->dirty |= CELL_NEW_BLEND;
@@ -68,6 +69,8 @@ cell_set_blend_color(struct pipe_context *pipe,
{
struct cell_context *cell = cell_context(pipe);
+ draw_flush(cell->draw);
+
cell->blend_color = *blend_color;
cell->dirty |= CELL_NEW_BLEND;
@@ -80,10 +83,7 @@ void *
cell_create_depth_stencil_alpha_state(struct pipe_context *pipe,
const struct pipe_depth_stencil_alpha_state *depth_stencil)
{
- struct pipe_depth_stencil_alpha_state *state =
- MALLOC(sizeof(struct pipe_depth_stencil_alpha_state));
- memcpy(state, depth_stencil, sizeof(struct pipe_depth_stencil_alpha_state));
- return state;
+ return mem_dup(depth_stencil, sizeof(*depth_stencil));
}
@@ -93,6 +93,8 @@ cell_bind_depth_stencil_alpha_state(struct pipe_context *pipe,
{
struct cell_context *cell = cell_context(pipe);
+ draw_flush(cell->draw);
+
cell->depth_stencil
= (const struct pipe_depth_stencil_alpha_state *) depth_stencil;
diff --git a/src/mesa/pipe/cell/ppu/cell_state_emit.c b/src/mesa/pipe/cell/ppu/cell_state_emit.c
index dbca900c35..5d2a786449 100644
--- a/src/mesa/pipe/cell/ppu/cell_state_emit.c
+++ b/src/mesa/pipe/cell/ppu/cell_state_emit.c
@@ -30,6 +30,18 @@
#include "cell_state.h"
#include "cell_state_emit.h"
#include "cell_batch.h"
+#include "cell_texture.h"
+
+
+static void
+emit_state_cmd(struct cell_context *cell, uint cmd,
+ const void *state, uint state_size)
+{
+ uint64_t *dst = (uint64_t *)
+ cell_batch_alloc(cell, ROUNDUP8(sizeof(uint64_t) + state_size));
+ *dst = cmd;
+ memcpy(dst + 1, state, state_size);
+}
@@ -50,23 +62,42 @@ cell_emit_state(struct cell_context *cell)
fb->height = cell->framebuffer.cbufs[0]->height;
}
+ if (cell->dirty & CELL_NEW_BLEND) {
+ emit_state_cmd(cell, CELL_CMD_STATE_BLEND,
+ cell->blend,
+ sizeof(struct pipe_blend_state));
+ }
+
if (cell->dirty & CELL_NEW_DEPTH_STENCIL) {
- uint cmd = CELL_CMD_STATE_DEPTH_STENCIL;
- cell_batch_append(cell, &cmd, 4);
- cell_batch_append(cell, cell->depth_stencil,
- sizeof(struct pipe_depth_stencil_alpha_state));
+ emit_state_cmd(cell, CELL_CMD_STATE_DEPTH_STENCIL,
+ cell->depth_stencil,
+ sizeof(struct pipe_depth_stencil_alpha_state));
}
if (cell->dirty & CELL_NEW_SAMPLER) {
- uint cmd = CELL_CMD_STATE_SAMPLER;
- cell_batch_append(cell, &cmd, 4);
- cell_batch_append(cell, cell->sampler[0],
- sizeof(struct pipe_sampler_state));
+ emit_state_cmd(cell, CELL_CMD_STATE_SAMPLER,
+ cell->sampler[0], sizeof(struct pipe_sampler_state));
+ }
+
+ if (cell->dirty & CELL_NEW_TEXTURE) {
+ struct cell_command_texture texture;
+ if (cell->texture[0]) {
+ texture.start = cell->texture[0]->tiled_data;
+ texture.width = cell->texture[0]->base.width[0];
+ texture.height = cell->texture[0]->base.height[0];
+ }
+ else {
+ texture.start = NULL;
+ texture.width = 0;
+ texture.height = 0;
+ }
+
+ emit_state_cmd(cell, CELL_CMD_STATE_TEXTURE,
+ &texture, sizeof(struct cell_command_texture));
}
if (cell->dirty & CELL_NEW_VERTEX_INFO) {
- uint cmd = CELL_CMD_STATE_VERTEX_INFO;
- cell_batch_append(cell, &cmd, 4);
- cell_batch_append(cell, &cell->vertex_info, sizeof(struct vertex_info));
+ emit_state_cmd(cell, CELL_CMD_STATE_VERTEX_INFO,
+ &cell->vertex_info, sizeof(struct vertex_info));
}
}
diff --git a/src/mesa/pipe/cell/ppu/cell_state_fs.c b/src/mesa/pipe/cell/ppu/cell_state_fs.c
index 81c2ac14dd..96a52273b0 100644
--- a/src/mesa/pipe/cell/ppu/cell_state_fs.c
+++ b/src/mesa/pipe/cell/ppu/cell_state_fs.c
@@ -45,7 +45,7 @@ void *
cell_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
- struct cell_context *cell = cell_context(pipe);
+ /*struct cell_context *cell = cell_context(pipe);*/
struct cell_fragment_shader_state *state;
state = CALLOC_STRUCT(cell_fragment_shader_state);
@@ -94,8 +94,6 @@ cell_bind_fs_state(struct pipe_context *pipe, void *fs)
void
cell_delete_fs_state(struct pipe_context *pipe, void *fs)
{
- struct cell_context *cell = cell_context(pipe);
-
struct cell_fragment_shader_state *state =
(struct cell_fragment_shader_state *) fs;
diff --git a/src/mesa/pipe/cell/ppu/cell_state_sampler.c b/src/mesa/pipe/cell/ppu/cell_state_sampler.c
index ae1eeb4620..ade6cc8338 100644
--- a/src/mesa/pipe/cell/ppu/cell_state_sampler.c
+++ b/src/mesa/pipe/cell/ppu/cell_state_sampler.c
@@ -30,21 +30,17 @@
*/
#include "pipe/p_util.h"
+#include "pipe/draw/draw_context.h"
#include "cell_context.h"
#include "cell_state.h"
-#if 0
#include "cell_texture.h"
-#include "cell_tile_cache.h"
-#endif
void *
cell_create_sampler_state(struct pipe_context *pipe,
const struct pipe_sampler_state *sampler)
{
- struct pipe_sampler_state *state = MALLOC( sizeof(struct pipe_sampler_state) );
- memcpy(state, sampler, sizeof(struct pipe_sampler_state));
- return state;
+ return mem_dup(sampler, sizeof(*sampler));
}
void
@@ -53,6 +49,8 @@ cell_bind_sampler_state(struct pipe_context *pipe,
{
struct cell_context *cell = cell_context(pipe);
+ draw_flush(cell->draw);
+
assert(unit < PIPE_MAX_SAMPLERS);
cell->sampler[unit] = (struct pipe_sampler_state *)sampler;
@@ -76,7 +74,11 @@ cell_set_sampler_texture(struct pipe_context *pipe,
{
struct cell_context *cell = cell_context(pipe);
+ draw_flush(cell->draw);
+
cell->texture[sampler] = texture;
+ cell_update_texture_mapping(cell);
+
cell->dirty |= CELL_NEW_TEXTURE;
}
diff --git a/src/mesa/pipe/cell/ppu/cell_texture.c b/src/mesa/pipe/cell/ppu/cell_texture.c
index 0a8190d983..df178d9ca2 100644
--- a/src/mesa/pipe/cell/ppu/cell_texture.c
+++ b/src/mesa/pipe/cell/ppu/cell_texture.c
@@ -79,31 +79,30 @@ cell_texture_layout(struct cell_texture * spt)
}
-void
-cell_texture_create(struct pipe_context *pipe, struct pipe_texture **pt)
+struct pipe_texture *
+cell_texture_create(struct pipe_context *pipe, const struct pipe_texture *templat)
{
- struct cell_texture *spt = REALLOC(*pt, sizeof(struct pipe_texture),
- sizeof(struct cell_texture));
+ struct cell_texture *spt = CALLOC_STRUCT(cell_texture);
+ if (!spt)
+ return NULL;
- if (spt) {
- memset(&spt->base + 1, 0,
- sizeof(struct cell_texture) - sizeof(struct pipe_texture));
+ spt->base = *templat;
- cell_texture_layout(spt);
+ cell_texture_layout(spt);
- spt->buffer = pipe->winsys->buffer_create(pipe->winsys, 32,
- PIPE_BUFFER_USAGE_PIXEL,
- spt->buffer_size);
+ spt->buffer = pipe->winsys->buffer_create(pipe->winsys, 32,
+ PIPE_BUFFER_USAGE_PIXEL,
+ spt->buffer_size);
- if (!spt->buffer) {
- FREE(spt);
- spt = NULL;
- }
+ if (!spt->buffer) {
+ FREE(spt);
+ return NULL;
}
- *pt = &spt->base;
+ return &spt->base;
}
+
void
cell_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)
{
@@ -163,3 +162,91 @@ cell_get_tex_surface(struct pipe_context *pipe,
}
return ps;
}
+
+
+
+static void
+tile_copy_data(uint w, uint h, uint tile_size, uint *dst, const uint *src)
+{
+ const uint tile_size2 = tile_size * tile_size;
+ const uint h_t = h / tile_size, w_t = w / tile_size;
+
+ uint it, jt; /* tile counters */
+ uint i, j; /* intra-tile counters */
+
+ for (it = 0; it < h_t; it++) {
+ for (jt = 0; jt < w_t; jt++) {
+ /* fill in tile (i, j) */
+ uint *tdst = dst + (it * w_t + jt) * tile_size2;
+ for (i = 0; i < tile_size; i++) {
+ for (j = 0; j < tile_size; j++) {
+ const uint srci = it * tile_size + i;
+ const uint srcj = jt * tile_size + j;
+ *tdst++ = src[srci * h + srcj];
+ }
+ }
+ }
+ }
+}
+
+
+
+/**
+ * Convert linear texture image data to tiled format for SPU usage.
+ */
+static void
+cell_tile_texture(struct cell_context *cell,
+ struct cell_texture *texture)
+{
+ uint face = 0, level = 0, zslice = 0;
+ struct pipe_surface *surf;
+ const uint w = texture->base.width[0], h = texture->base.height[0];
+ const uint *src;
+
+ /* temporary restrictions: */
+ assert(w >= TILE_SIZE);
+ assert(h >= TILE_SIZE);
+ assert(w % TILE_SIZE == 0);
+ assert(h % TILE_SIZE == 0);
+
+ surf = cell_get_tex_surface(&cell->pipe, &texture->base, face, level, zslice);
+ ASSERT(surf);
+
+ src = (const uint *) pipe_surface_map(surf);
+
+ if (texture->tiled_data) {
+ align_free(texture->tiled_data);
+ }
+ texture->tiled_data = align_malloc(w * h * 4, 16);
+
+ tile_copy_data(w, h, TILE_SIZE, texture->tiled_data, src);
+
+ pipe_surface_unmap(surf);
+
+ pipe_surface_reference(&surf, NULL);
+}
+
+
+
+void
+cell_update_texture_mapping(struct cell_context *cell)
+{
+ uint face = 0, level = 0, zslice = 0;
+
+ if (cell->texture[0])
+ cell_tile_texture(cell, cell->texture[0]);
+#if 0
+ if (cell->tex_surf && cell->tex_map) {
+ pipe_surface_unmap(cell->tex_surf);
+ cell->tex_map = NULL;
+ }
+
+ /* XXX free old surface */
+
+ cell->tex_surf = cell_get_tex_surface(&cell->pipe,
+ &cell->texture[0]->base,
+ face, level, zslice);
+
+ cell->tex_map = pipe_surface_map(cell->tex_surf);
+#endif
+}
diff --git a/src/mesa/pipe/cell/ppu/cell_texture.h b/src/mesa/pipe/cell/ppu/cell_texture.h
index ef5808c086..0264fed88e 100644
--- a/src/mesa/pipe/cell/ppu/cell_texture.h
+++ b/src/mesa/pipe/cell/ppu/cell_texture.h
@@ -46,6 +46,8 @@ struct cell_texture
*/
struct pipe_buffer *buffer;
unsigned long buffer_size;
+
+ void *tiled_data; /* XXX this may be temporary */ /*ALIGN16*/
};
@@ -58,8 +60,9 @@ cell_texture(struct pipe_texture *pt)
-extern void
-cell_texture_create(struct pipe_context *pipe, struct pipe_texture **pt);
+extern struct pipe_texture *
+cell_texture_create(struct pipe_context *pipe,
+ const struct pipe_texture *templat);
extern void
cell_texture_release(struct pipe_context *pipe, struct pipe_texture **pt);
@@ -70,4 +73,8 @@ cell_get_tex_surface(struct pipe_context *pipe,
unsigned face, unsigned level, unsigned zslice);
+extern void
+cell_update_texture_mapping(struct cell_context *cell);
+
+
#endif /* CELL_TEXTURE */
diff --git a/src/mesa/pipe/cell/ppu/cell_vbuf.c b/src/mesa/pipe/cell/ppu/cell_vbuf.c
index ee572b3a51..e9fafe492e 100644
--- a/src/mesa/pipe/cell/ppu/cell_vbuf.c
+++ b/src/mesa/pipe/cell/ppu/cell_vbuf.c
@@ -39,8 +39,7 @@
#include "pipe/draw/draw_vbuf.h"
-/** Allow prim indexes, verts to be inlined after RENDER command */
-#define ALLOW_INLINE_INDEXES 1
+/** Allow vertex data to be inlined after RENDER command */
#define ALLOW_INLINE_VERTS 1
@@ -52,9 +51,10 @@ struct cell_vbuf_render
{
struct vbuf_render base;
struct cell_context *cell;
- uint prim;
- uint vertex_size;
- void *vertex_buffer;
+ uint prim; /**< PIPE_PRIM_x */
+ uint vertex_size; /**< in bytes */
+ void *vertex_buffer; /**< just for debug, really */
+ uint vertex_buf; /**< in [0, CELL_NUM_BUFFERS-1] */
};
@@ -81,14 +81,46 @@ cell_vbuf_allocate_vertices(struct vbuf_render *vbr,
{
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
/*printf("Alloc verts %u * %u\n", vertex_size, nr_vertices);*/
- assert(!cvbr->vertex_buffer);
- cvbr->vertex_buffer = align_malloc(vertex_size * nr_vertices, 16);
+
+ 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_size = vertex_size;
return cvbr->vertex_buffer;
}
static void
+cell_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices,
+ unsigned vertex_size, unsigned vertices_used)
+{
+ struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
+ struct cell_context *cell = cvbr->cell;
+
+ /*
+ printf("%s vertex_buf = %u count = %u\n",
+ __FUNCTION__, cvbr->vertex_buf, vertices_used);
+ */
+
+ /* Tell SPUs they can release the vert buf */
+ if (cvbr->vertex_buf != ~0U) {
+ struct cell_command_release_verts *release
+ = (struct cell_command_release_verts *)
+ cell_batch_alloc(cell, sizeof(struct cell_command_release_verts));
+ release->opcode = CELL_CMD_RELEASE_VERTS;
+ release->vertex_buf = cvbr->vertex_buf;
+ }
+
+ cvbr->vertex_buf = ~0;
+ cell_flush_int(&cell->pipe, 0x0);
+
+ assert(vertices == cvbr->vertex_buffer);
+ cvbr->vertex_buffer = NULL;
+}
+
+
+
+static void
cell_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
{
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
@@ -106,17 +138,24 @@ cell_vbuf_draw(struct vbuf_render *vbr,
struct cell_context *cell = cvbr->cell;
float xmin, ymin, xmax, ymax;
uint i;
- uint nr_vertices = 0;
+ uint nr_vertices = 0, min_index = ~0;
const void *vertices = cvbr->vertex_buffer;
const uint vertex_size = cvbr->vertex_size;
for (i = 0; i < nr_indices; i++) {
if (indices[i] > nr_vertices)
nr_vertices = indices[i];
+ if (indices[i] < min_index)
+ min_index = indices[i];
}
nr_vertices++;
#if 0
+ /*if (min_index > 0)*/
+ printf("%s min_index = %u\n", __FUNCTION__, min_index);
+#endif
+
+#if 0
printf("cell_vbuf_draw() nr_indices = %u nr_verts = %u\n",
nr_indices, nr_vertices);
printf(" ");
@@ -137,7 +176,7 @@ cell_vbuf_draw(struct vbuf_render *vbr,
/* compute x/y bounding box */
xmin = ymin = 1e50;
xmax = ymax = -1e50;
- for (i = 0; i < nr_vertices; i++) {
+ for (i = min_index; i < nr_vertices; i++) {
const float *v = (float *) ((ubyte *) vertices + i * vertex_size);
if (v[0] < xmin)
xmin = v[0];
@@ -148,83 +187,68 @@ cell_vbuf_draw(struct vbuf_render *vbr,
if (v[1] > ymax)
ymax = v[1];
}
+#if 0
+ printf("PPU Bounds %g, %g .. %g, %g\n", xmin, ymin, xmax, ymax);
+ fflush(stdout);
+#endif
if (cvbr->prim != PIPE_PRIM_TRIANGLES)
return; /* only render tris for now */
/* build/insert batch RENDER command */
{
- const uint index_bytes = ROUNDUP4(nr_indices * 2);
+ const uint index_bytes = ROUNDUP8(nr_indices * 2);
const uint vertex_bytes = nr_vertices * 4 * cell->vertex_info.size;
+ const uint batch_size = sizeof(struct cell_command_render) + index_bytes;
struct cell_command_render *render
= (struct cell_command_render *)
- cell_batch_alloc(cell, sizeof(*render));
+ cell_batch_alloc(cell, batch_size);
+
render->opcode = CELL_CMD_RENDER;
render->prim_type = cvbr->prim;
render->num_indexes = nr_indices;
- if (ALLOW_INLINE_INDEXES &&
- index_bytes <= cell_batch_free_space(cell)) {
- /* indices inlined, right after render cmd */
- void *dst = cell_batch_alloc(cell, index_bytes);
- memcpy(dst, indices, nr_indices * 2);
- render->inline_indexes = TRUE;
- render->index_data = NULL;
- }
- else {
- /* indices in separate buffer */
- render->inline_indexes = FALSE;
- render->index_data = indices;
- ASSERT_ALIGN16(render->index_data);
- }
+ render->min_index = min_index;
+
+ /* append indices after render command */
+ memcpy(render + 1, indices, nr_indices * 2);
+ /* if there's room, append vertices after the indices, else leave
+ * vertices in the original/separate buffer.
+ */
render->vertex_size = 4 * cell->vertex_info.size;
render->num_verts = nr_vertices;
if (ALLOW_INLINE_VERTS &&
- render->inline_indexes &&
- vertex_bytes <= cell_batch_free_space(cell)) {
- /* vertex data inlined, after indices */
- void *dst = cell_batch_alloc(cell, vertex_bytes);
+ min_index == 0 &&
+ vertex_bytes + 16 <= cell_batch_free_space(cell)) {
+ /* vertex data inlined, after indices, at 16-byte boundary */
+ void *dst = cell_batch_alloc_aligned(cell, vertex_bytes, 16);
memcpy(dst, vertices, vertex_bytes);
render->inline_verts = TRUE;
- render->vertex_data = NULL;
+ render->vertex_buf = ~0;
}
else {
+ /* vertex data in separate buffer */
render->inline_verts = FALSE;
- render->vertex_data = vertices;
- ASSERT_ALIGN16(render->vertex_data);
+ ASSERT(cvbr->vertex_buf >= 0);
+ render->vertex_buf = cvbr->vertex_buf;
}
-
render->xmin = xmin;
render->ymin = ymin;
render->xmax = xmax;
render->ymax = ymax;
}
-#if 01
- /* XXX this is temporary */
+#if 0
+ /* helpful for debug */
cell_flush_int(&cell->pipe, PIPE_FLUSH_WAIT);
#endif
}
static void
-cell_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices,
- unsigned vertex_size, unsigned vertices_used)
-{
- struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
-
- /*printf("Free verts %u * %u\n", vertex_size, vertices_used);*/
- align_free(vertices);
-
- assert(vertices == cvbr->vertex_buffer);
- cvbr->vertex_buffer = NULL;
-}
-
-
-static void
cell_vbuf_destroy(struct vbuf_render *vbr)
{
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
@@ -244,8 +268,15 @@ cell_init_vbuf(struct cell_context *cell)
cell->vbuf_render = CALLOC_STRUCT(cell_vbuf_render);
- cell->vbuf_render->base.max_indices = CELL_MAX_VBUF_INDEXES;
- cell->vbuf_render->base.max_vertex_buffer_bytes = CELL_MAX_VBUF_SIZE;
+ /* The max number of indexes is what can fix into a batch buffer,
+ * minus the render and release-verts commands.
+ */
+ cell->vbuf_render->base.max_indices
+ = (CELL_BUFFER_SIZE
+ - sizeof(struct cell_command_render)
+ - sizeof(struct cell_command_release_verts))
+ / sizeof(ushort);
+ cell->vbuf_render->base.max_vertex_buffer_bytes = CELL_BUFFER_SIZE;
cell->vbuf_render->base.get_vertex_info = cell_vbuf_get_vertex_info;
cell->vbuf_render->base.allocate_vertices = cell_vbuf_allocate_vertices;
@@ -255,6 +286,9 @@ cell_init_vbuf(struct cell_context *cell)
cell->vbuf_render->base.destroy = cell_vbuf_destroy;
cell->vbuf_render->cell = cell;
+#if 1
+ cell->vbuf_render->vertex_buf = ~0;
+#endif
cell->vbuf = draw_vbuf_stage(cell->draw, &cell->vbuf_render->base);
}
diff --git a/src/mesa/pipe/cell/ppu/cell_vertex_shader.c b/src/mesa/pipe/cell/ppu/cell_vertex_shader.c
new file mode 100644
index 0000000000..80dd500b34
--- /dev/null
+++ b/src/mesa/pipe/cell/ppu/cell_vertex_shader.c
@@ -0,0 +1,120 @@
+/*
+ * (C) Copyright IBM Corporation 2008
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file cell_vertex_shader.c
+ * Vertex shader interface routines for Cell.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "pipe/p_defines.h"
+#include "pipe/p_context.h"
+#include "pipe/p_winsys.h"
+
+#include "cell_context.h"
+#include "cell_draw_arrays.h"
+#include "cell_spu.h"
+#include "cell_batch.h"
+
+#include "pipe/cell/common.h"
+#include "pipe/draw/draw_context.h"
+#include "pipe/draw/draw_private.h"
+
+/**
+ * Run the vertex shader on all vertices in the vertex queue.
+ * Called by the draw module when the vertx cache needs to be flushed.
+ */
+void
+cell_vertex_shader_queue_flush(struct draw_context *draw)
+{
+ struct cell_context *const cell =
+ (struct cell_context *) draw->driver_private;
+ struct cell_command_vs *const vs = &cell_global.command[0].vs;
+ uint64_t *batch;
+ struct cell_array_info *array_info;
+ unsigned i, j;
+
+ assert(draw->vs.queue_nr != 0);
+
+ /* XXX: do this on statechange:
+ */
+ draw_update_vertex_fetch(draw);
+
+ for (i = 0; i < draw->vertex_fetch.nr_attrs; i++) {
+ batch = cell_batch_alloc(cell, sizeof(batch[0]) + sizeof(*array_info));
+
+ batch[0] = CELL_CMD_STATE_VS_ARRAY_INFO;
+
+ array_info = (struct cell_array_info *) &batch[1];
+ assert(draw->vertex_fetch.src_ptr[i] != NULL);
+ array_info->base = (uintptr_t) draw->vertex_fetch.src_ptr[i];
+ array_info->attr = i;
+ array_info->pitch = draw->vertex_fetch.pitch[i];
+ array_info->format = draw->vertex_element[i].src_format;
+ }
+
+ batch = cell_batch_alloc(cell, sizeof(batch[0])
+ + sizeof(struct pipe_viewport_state));
+ batch[0] = CELL_CMD_STATE_VIEWPORT;
+ (void) memcpy(&batch[1], &draw->viewport,
+ sizeof(struct pipe_viewport_state));
+
+ cell_batch_flush(cell);
+
+ vs->opcode = CELL_CMD_VS_EXECUTE;
+ vs->shader.num_outputs = draw->num_vs_outputs;
+ vs->shader.declarations = (uintptr_t) draw->machine.Declarations;
+ vs->shader.num_declarations = draw->machine.NumDeclarations;
+ vs->shader.instructions = (uintptr_t) draw->machine.Instructions;
+ vs->shader.num_instructions = draw->machine.NumInstructions;
+ vs->shader.uniforms = (uintptr_t) draw->user.constants;
+ vs->shader.immediates = (uintptr_t) draw->machine.Imms;
+ vs->shader.num_immediates = draw->machine.ImmLimit / 4;
+ vs->nr_attrs = draw->vertex_fetch.nr_attrs;
+
+ (void) memcpy(vs->plane, draw->plane, sizeof(draw->plane));
+ vs->nr_planes = draw->nr_planes;
+
+ for (i = 0; i < draw->vs.queue_nr; i += SPU_VERTS_PER_BATCH) {
+ const unsigned n = MIN2(SPU_VERTS_PER_BATCH, draw->vs.queue_nr - i);
+
+ for (j = 0; j < n; j++) {
+ vs->elts[j] = draw->vs.queue[i + j].elt;
+ vs->vOut[j] = (uintptr_t) draw->vs.queue[i + j].dest;
+ }
+
+ for (/* empty */; j < SPU_VERTS_PER_BATCH; j++) {
+ vs->elts[j] = vs->elts[0];
+ vs->vOut[j] = vs->vOut[0];
+ }
+
+ vs->num_elts = n;
+ send_mbox_message(cell_global.spe_contexts[0], CELL_CMD_VS_EXECUTE);
+
+ cell_flush_int(& cell->pipe, PIPE_FLUSH_WAIT);
+ }
+
+ draw->vs.queue_nr = 0;
+}