diff options
Diffstat (limited to 'src/gallium/drivers/cell')
20 files changed, 409 insertions, 76 deletions
diff --git a/src/gallium/drivers/cell/common.h b/src/gallium/drivers/cell/common.h index d59e4f7036..b0928fefd2 100644 --- a/src/gallium/drivers/cell/common.h +++ b/src/gallium/drivers/cell/common.h @@ -92,8 +92,9 @@ #define CELL_CMD_STATE_BIND_VS 18 #define CELL_CMD_STATE_BLEND 19 #define CELL_CMD_STATE_ATTRIB_FETCH 20 -#define CELL_CMD_VS_EXECUTE 21 -#define CELL_CMD_FLUSH_BUFFER_RANGE 22 +#define CELL_CMD_STATE_LOGICOP 21 +#define CELL_CMD_VS_EXECUTE 22 +#define CELL_CMD_FLUSH_BUFFER_RANGE 23 #define CELL_NUM_BUFFERS 4 @@ -124,6 +125,12 @@ struct cell_command_blend { }; +struct cell_command_logicop { + uint64_t base; /**< Effective address of code start. */ + unsigned size; /**< Size in bytes of test code. */ +}; + + /** * Tell SPUs about the framebuffer size, location */ diff --git a/src/gallium/drivers/cell/ppu/cell_context.c b/src/gallium/drivers/cell/ppu/cell_context.c index ccbbd1d331..12eb5aa254 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.c +++ b/src/gallium/drivers/cell/ppu/cell_context.c @@ -103,8 +103,8 @@ cell_create_context(struct pipe_screen *screen, cell->pipe.destroy = cell_destroy_context; /* state setters */ - cell->pipe.set_vertex_buffer = cell_set_vertex_buffer; - cell->pipe.set_vertex_element = cell_set_vertex_element; + cell->pipe.set_vertex_buffers = cell_set_vertex_buffers; + cell->pipe.set_vertex_elements = cell_set_vertex_elements; cell->pipe.draw_arrays = cell_draw_arrays; cell->pipe.draw_elements = cell_draw_elements; diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h index 9e79db0ace..7f656a9744 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.h +++ b/src/gallium/drivers/cell/ppu/cell_context.h @@ -92,6 +92,8 @@ struct cell_context const struct cell_vertex_shader_state *vs; const struct cell_fragment_shader_state *fs; + struct spe_function logic_op; + struct pipe_blend_color blend_color; struct pipe_clip_state clip; struct pipe_constant_buffer constants[2]; @@ -101,8 +103,8 @@ struct cell_context struct cell_texture *texture[PIPE_MAX_SAMPLERS]; uint num_textures; struct pipe_viewport_state viewport; - struct pipe_vertex_buffer vertex_buffer[PIPE_ATTRIB_MAX]; - struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX]; + struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS]; ubyte *zsbuf_map; @@ -139,7 +141,7 @@ struct cell_context struct spe_function attrib_fetch; - unsigned attrib_fetch_offsets[PIPE_ATTRIB_MAX]; + unsigned attrib_fetch_offsets[PIPE_MAX_ATTRIBS]; }; diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c index c839fb4d12..b896252f81 100644 --- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c +++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c @@ -123,7 +123,7 @@ cell_draw_elements(struct pipe_context *pipe, /* * Map vertex buffers */ - for (i = 0; i < PIPE_ATTRIB_MAX; i++) { + for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { if (sp->vertex_buffer[i].buffer) { void *buf = pipe->winsys->buffer_map(pipe->winsys, sp->vertex_buffer[i].buffer, @@ -151,7 +151,7 @@ cell_draw_elements(struct pipe_context *pipe, /* * unmap vertex/index buffers - will cause draw module to flush */ - for (i = 0; i < PIPE_ATTRIB_MAX; i++) { + for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { if (sp->vertex_buffer[i].buffer) { draw_set_mapped_vertex_buffer(draw, i, NULL); pipe->winsys->buffer_unmap(pipe->winsys, sp->vertex_buffer[i].buffer); diff --git a/src/gallium/drivers/cell/ppu/cell_flush.c b/src/gallium/drivers/cell/ppu/cell_flush.c index 66a5627d84..3aaf3de668 100644 --- a/src/gallium/drivers/cell/ppu/cell_flush.c +++ b/src/gallium/drivers/cell/ppu/cell_flush.c @@ -35,12 +35,19 @@ void -cell_flush(struct pipe_context *pipe, unsigned flags) +cell_flush(struct pipe_context *pipe, unsigned flags, + struct pipe_fence_handle **fence) { struct cell_context *cell = cell_context(pipe); + if (fence) { + *fence = NULL; + /* XXX: Implement real fencing */ + flags |= CELL_FLUSH_WAIT; + } + if (flags & PIPE_FLUSH_SWAPBUFFERS) - flags |= PIPE_FLUSH_WAIT; + flags |= CELL_FLUSH_WAIT; draw_flush( cell->draw ); cell_flush_int(pipe, flags); @@ -58,7 +65,7 @@ cell_flush_int(struct pipe_context *pipe, unsigned flags) ASSERT(!flushing); flushing = TRUE; - if (flags & PIPE_FLUSH_WAIT) { + if (flags & CELL_FLUSH_WAIT) { uint64_t *cmd = (uint64_t *) cell_batch_alloc(cell, sizeof(uint64_t)); *cmd = CELL_CMD_FINISH; } @@ -72,7 +79,7 @@ cell_flush_int(struct pipe_context *pipe, unsigned flags) } #endif - if (flags & PIPE_FLUSH_WAIT) { + if (flags & CELL_FLUSH_WAIT) { /* Wait for ack */ for (i = 0; i < cell->num_spus; i++) { uint k = wait_mbox_message(cell_global.spe_contexts[i]); diff --git a/src/gallium/drivers/cell/ppu/cell_flush.h b/src/gallium/drivers/cell/ppu/cell_flush.h index 7f940ae76b..8f0645c429 100644 --- a/src/gallium/drivers/cell/ppu/cell_flush.h +++ b/src/gallium/drivers/cell/ppu/cell_flush.h @@ -29,8 +29,11 @@ #ifndef CELL_FLUSH #define CELL_FLUSH +#define CELL_FLUSH_WAIT 0x80000000 + extern void -cell_flush(struct pipe_context *pipe, unsigned flags); +cell_flush(struct pipe_context *pipe, unsigned flags, + struct pipe_fence_handle **fence); extern void cell_flush_int(struct pipe_context *pipe, unsigned flags); diff --git a/src/gallium/drivers/cell/ppu/cell_state.h b/src/gallium/drivers/cell/ppu/cell_state.h index 31ce505e21..82580ea35a 100644 --- a/src/gallium/drivers/cell/ppu/cell_state.h +++ b/src/gallium/drivers/cell/ppu/cell_state.h @@ -48,13 +48,13 @@ #define CELL_NEW_VERTEX_INFO 0x8000 -void cell_set_vertex_element(struct pipe_context *, - unsigned index, - const struct pipe_vertex_element *); +void cell_set_vertex_elements(struct pipe_context *, + unsigned count, + const struct pipe_vertex_element *); -void cell_set_vertex_buffer(struct pipe_context *, - unsigned index, - const struct pipe_vertex_buffer *); +void cell_set_vertex_buffers(struct pipe_context *, + unsigned count, + const struct pipe_vertex_buffer *); void cell_update_derived( struct cell_context *softpipe ); diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c index 5709b48f12..4c75caa025 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_emit.c +++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c @@ -29,6 +29,7 @@ #include "cell_context.h" #include "cell_state.h" #include "cell_state_emit.h" +#include "cell_state_per_fragment.h" #include "cell_batch.h" #include "cell_texture.h" #include "draw/draw_context.h" @@ -50,6 +51,23 @@ emit_state_cmd(struct cell_context *cell, uint cmd, void cell_emit_state(struct cell_context *cell) { + if (cell->dirty & (CELL_NEW_FRAMEBUFFER | CELL_NEW_BLEND)) { + struct cell_command_logicop logicop; + + if (cell->logic_op.store != NULL) { + spe_release_func(& cell->logic_op); + } + + cell_generate_logic_op(& cell->logic_op, + & cell->blend->base, + cell->framebuffer.cbufs[0]); + + logicop.base = (intptr_t) cell->logic_op.store; + logicop.size = 64 * 4; + emit_state_cmd(cell, CELL_CMD_STATE_LOGICOP, &logicop, + sizeof(logicop)); + } + if (cell->dirty & CELL_NEW_FRAMEBUFFER) { struct pipe_surface *cbuf = cell->framebuffer.cbufs[0]; struct pipe_surface *zbuf = cell->framebuffer.zsbuf; diff --git a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c index c750b1d89d..f10025bd7c 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c +++ b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c @@ -977,7 +977,6 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) spe_allocate_register(f, 13), spe_allocate_register(f, 14), }; - const int mask = spe_allocate_register(f, 15); unsigned func[4]; unsigned sF[4]; unsigned dF[4]; @@ -1114,9 +1113,6 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) func[i], sF[i], dF[i], frag[i], src_factor[i], pixel[i], dst_factor[i]); - spe_selb(f, frag[i], pixel[i], frag[i], mask); - } else { - spe_or(f, frag[i], pixel[i], pixel[i]); } } @@ -1146,3 +1142,260 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) } #endif } + + +int PC_OFFSET(const struct spe_function *f, const void *d) +{ + const intptr_t pc = (intptr_t) f->csr; + const intptr_t ea = ~0x0f & (intptr_t) d; + + return (ea - pc) >> 2; +} + + +/** + * Generate code to perform color conversion and logic op + * + * \bug + * The code generated by this function should also perform dithering. + * + * \bug + * The code generated by this function should also perform color-write + * masking. + * + * \bug + * This routine is hard-coded to only work with ARGB8 data. + */ +void +cell_generate_logic_op(struct spe_function *f, struct pipe_blend_state *blend, + struct pipe_surface *surf) +{ + const unsigned logic_op = (blend->logicop_enable) + ? blend->logicop_func : PIPE_LOGICOP_COPY; + + /* This code generates a maximum of 37 instructions. An additional 32 + * bytes (equiv. to 8 instructions) are needed for data storage. Round up + * to 64 to make it a happy power-of-two. + */ + spe_init_func(f, 4 * 64); + + + /* Pixel colors in framebuffer format in AoS layout. + */ + const int pixel[4] = { + spe_allocate_register(f, 3), + spe_allocate_register(f, 4), + spe_allocate_register(f, 5), + spe_allocate_register(f, 6), + }; + + /* Fragment colors stored as floats in SoA layout. + */ + const int frag[4] = { + spe_allocate_register(f, 7), + spe_allocate_register(f, 8), + spe_allocate_register(f, 9), + spe_allocate_register(f, 10), + }; + + const int mask = spe_allocate_register(f, 11); + + + /* Short-circuit the noop and invert cases. + */ + if ((logic_op == PIPE_LOGICOP_NOOP) || (blend->colormask == 0)) { + spe_bi(f, 0, 0, 0); + return; + } else if (logic_op == PIPE_LOGICOP_INVERT) { + spe_nor(f, pixel[0], pixel[0], pixel[0]); + spe_nor(f, pixel[1], pixel[1], pixel[1]); + spe_nor(f, pixel[2], pixel[2], pixel[2]); + spe_nor(f, pixel[3], pixel[3], pixel[3]); + spe_bi(f, 0, 0, 0); + return; + } + + + const int tmp[4] = { + spe_allocate_available_register(f), + spe_allocate_available_register(f), + spe_allocate_available_register(f), + spe_allocate_available_register(f), + }; + + const int shuf_xpose_hi = spe_allocate_available_register(f); + const int shuf_xpose_lo = spe_allocate_available_register(f); + const int shuf_color = spe_allocate_available_register(f); + + + /* Pointer to the begining of the function's private data area. + */ + uint32_t *const data = ((uint32_t *) f->store) + (64 - 8); + + + /* Convert fragment colors to framebuffer format in AoS layout. + */ + data[0] = 0x00010203; + data[1] = 0x10111213; + data[2] = 0x04050607; + data[3] = 0x14151617; + + data[4] = 0x0c000408; + data[5] = 0x80808080; + data[6] = 0x80808080; + data[7] = 0x80808080; + + spe_ilh(f, tmp[0], 0x0808); + spe_lqr(f, shuf_xpose_hi, PC_OFFSET(f, data+0)); + spe_lqr(f, shuf_color, PC_OFFSET(f, data+4)); + spe_a(f, shuf_xpose_lo, shuf_xpose_hi, tmp[0]); + + spe_shufb(f, tmp[0], frag[0], frag[2], shuf_xpose_hi); + spe_shufb(f, tmp[1], frag[0], frag[2], shuf_xpose_lo); + spe_shufb(f, tmp[2], frag[1], frag[3], shuf_xpose_hi); + spe_shufb(f, tmp[3], frag[1], frag[3], shuf_xpose_lo); + + spe_shufb(f, frag[0], tmp[0], tmp[2], shuf_xpose_hi); + spe_shufb(f, frag[1], tmp[0], tmp[2], shuf_xpose_lo); + spe_shufb(f, frag[2], tmp[1], tmp[3], shuf_xpose_hi); + spe_shufb(f, frag[3], tmp[1], tmp[3], shuf_xpose_lo); + + spe_cfltu(f, frag[0], frag[0], 32); + spe_cfltu(f, frag[1], frag[1], 32); + spe_cfltu(f, frag[2], frag[2], 32); + spe_cfltu(f, frag[3], frag[3], 32); + + spe_shufb(f, frag[0], frag[0], pixel[0], shuf_color); + spe_shufb(f, frag[1], frag[1], pixel[1], shuf_color); + spe_shufb(f, frag[2], frag[2], pixel[2], shuf_color); + spe_shufb(f, frag[3], frag[3], pixel[3], shuf_color); + + + /* If logic op is enabled, perform the requested logical operation on the + * converted fragment colors and the pixel colors. + */ + switch (logic_op) { + case PIPE_LOGICOP_CLEAR: + spe_il(f, frag[0], 0); + spe_il(f, frag[1], 0); + spe_il(f, frag[2], 0); + spe_il(f, frag[3], 0); + break; + case PIPE_LOGICOP_NOR: + spe_nor(f, frag[0], frag[0], pixel[0]); + spe_nor(f, frag[1], frag[1], pixel[1]); + spe_nor(f, frag[2], frag[2], pixel[2]); + spe_nor(f, frag[3], frag[3], pixel[3]); + break; + case PIPE_LOGICOP_AND_INVERTED: + spe_andc(f, frag[0], pixel[0], frag[0]); + spe_andc(f, frag[1], pixel[1], frag[1]); + spe_andc(f, frag[2], pixel[2], frag[2]); + spe_andc(f, frag[3], pixel[3], frag[3]); + break; + case PIPE_LOGICOP_COPY_INVERTED: + spe_nor(f, frag[0], frag[0], frag[0]); + spe_nor(f, frag[1], frag[1], frag[1]); + spe_nor(f, frag[2], frag[2], frag[2]); + spe_nor(f, frag[3], frag[3], frag[3]); + break; + case PIPE_LOGICOP_AND_REVERSE: + spe_andc(f, frag[0], frag[0], pixel[0]); + spe_andc(f, frag[1], frag[1], pixel[1]); + spe_andc(f, frag[2], frag[2], pixel[2]); + spe_andc(f, frag[3], frag[3], pixel[3]); + break; + case PIPE_LOGICOP_XOR: + spe_xor(f, frag[0], frag[0], pixel[0]); + spe_xor(f, frag[1], frag[1], pixel[1]); + spe_xor(f, frag[2], frag[2], pixel[2]); + spe_xor(f, frag[3], frag[3], pixel[3]); + break; + case PIPE_LOGICOP_NAND: + spe_nand(f, frag[0], frag[0], pixel[0]); + spe_nand(f, frag[1], frag[1], pixel[1]); + spe_nand(f, frag[2], frag[2], pixel[2]); + spe_nand(f, frag[3], frag[3], pixel[3]); + break; + case PIPE_LOGICOP_AND: + spe_and(f, frag[0], frag[0], pixel[0]); + spe_and(f, frag[1], frag[1], pixel[1]); + spe_and(f, frag[2], frag[2], pixel[2]); + spe_and(f, frag[3], frag[3], pixel[3]); + break; + case PIPE_LOGICOP_EQUIV: + spe_eqv(f, frag[0], frag[0], pixel[0]); + spe_eqv(f, frag[1], frag[1], pixel[1]); + spe_eqv(f, frag[2], frag[2], pixel[2]); + spe_eqv(f, frag[3], frag[3], pixel[3]); + break; + case PIPE_LOGICOP_OR_INVERTED: + spe_orc(f, frag[0], pixel[0], frag[0]); + spe_orc(f, frag[1], pixel[1], frag[1]); + spe_orc(f, frag[2], pixel[2], frag[2]); + spe_orc(f, frag[3], pixel[3], frag[3]); + break; + case PIPE_LOGICOP_COPY: + break; + case PIPE_LOGICOP_OR_REVERSE: + spe_orc(f, frag[0], frag[0], pixel[0]); + spe_orc(f, frag[1], frag[1], pixel[1]); + spe_orc(f, frag[2], frag[2], pixel[2]); + spe_orc(f, frag[3], frag[3], pixel[3]); + break; + case PIPE_LOGICOP_OR: + spe_or(f, frag[0], frag[0], pixel[0]); + spe_or(f, frag[1], frag[1], pixel[1]); + spe_or(f, frag[2], frag[2], pixel[2]); + spe_or(f, frag[3], frag[3], pixel[3]); + break; + case PIPE_LOGICOP_SET: + spe_il(f, frag[0], ~0); + spe_il(f, frag[1], ~0); + spe_il(f, frag[2], ~0); + spe_il(f, frag[3], ~0); + break; + + /* These two cases are short-circuited above. + */ + case PIPE_LOGICOP_INVERT: + case PIPE_LOGICOP_NOOP: + default: + assert(0); + } + + + /* Apply fragment mask. + */ + spe_ilh(f, tmp[0], 0x0000); + spe_ilh(f, tmp[1], 0x0404); + spe_ilh(f, tmp[2], 0x0808); + spe_ilh(f, tmp[3], 0x0c0c); + + spe_shufb(f, tmp[0], mask, mask, tmp[0]); + spe_shufb(f, tmp[1], mask, mask, tmp[1]); + spe_shufb(f, tmp[2], mask, mask, tmp[2]); + spe_shufb(f, tmp[3], mask, mask, tmp[3]); + + spe_selb(f, pixel[0], pixel[0], frag[0], tmp[0]); + spe_selb(f, pixel[1], pixel[1], frag[1], tmp[1]); + spe_selb(f, pixel[2], pixel[2], frag[2], tmp[2]); + spe_selb(f, pixel[3], pixel[3], frag[3], tmp[3]); + + spe_bi(f, 0, 0, 0); + +#if 0 + { + const uint32_t *p = f->store; + unsigned i; + + printf("# %u instructions\n", f->csr - f->store); + + printf("\t.text\n"); + for (i = 0; i < 64; i++) { + printf("\t.long\t0x%04x\n", p[i]); + } + fflush(stdout); + } +#endif +} diff --git a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.h b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.h index f699247f9e..ab4de96c69 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.h +++ b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.h @@ -31,4 +31,8 @@ cell_generate_depth_stencil_test(struct cell_depth_stencil_alpha_state *cdsa); extern void cell_generate_alpha_blend(struct cell_blend_state *cb); +extern void +cell_generate_logic_op(struct spe_function *f, struct pipe_blend_state *blend, + struct pipe_surface *surf); + #endif /* CELL_STATE_PER_FRAGMENT_H */ diff --git a/src/gallium/drivers/cell/ppu/cell_state_vertex.c b/src/gallium/drivers/cell/ppu/cell_state_vertex.c index 563831b62d..6c83b8dc72 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_vertex.c +++ b/src/gallium/drivers/cell/ppu/cell_state_vertex.c @@ -36,28 +36,34 @@ void -cell_set_vertex_element(struct pipe_context *pipe, - unsigned index, - const struct pipe_vertex_element *attrib) +cell_set_vertex_elements(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_element *elements) { struct cell_context *cell = cell_context(pipe); - assert(index < PIPE_ATTRIB_MAX); - cell->vertex_element[index] = *attrib; /* struct copy */ + + assert(count <= PIPE_MAX_ATTRIBS); + + memcpy(cell->vertex_element, elements, count * sizeof(elements[0])); + cell->dirty |= CELL_NEW_VERTEX; - draw_set_vertex_element(cell->draw, index, attrib); + draw_set_vertex_elements(cell->draw, count, elements); } void -cell_set_vertex_buffer(struct pipe_context *pipe, - unsigned index, - const struct pipe_vertex_buffer *buffer) +cell_set_vertex_buffers(struct pipe_context *pipe, + unsigned count, + const struct pipe_vertex_buffer *buffers) { struct cell_context *cell = cell_context(pipe); - assert(index < PIPE_ATTRIB_MAX); - cell->vertex_buffer[index] = *buffer; /* struct copy */ + + assert(count <= PIPE_MAX_ATTRIBS); + + memcpy(cell->vertex_buffer, buffers, count * sizeof(buffers[0])); + cell->dirty |= CELL_NEW_VERTEX; - draw_set_vertex_buffer(cell->draw, index, buffer); + draw_set_vertex_buffers(cell->draw, count, buffers); } diff --git a/src/gallium/drivers/cell/ppu/cell_vbuf.c b/src/gallium/drivers/cell/ppu/cell_vbuf.c index cc727ff4ed..3a181b585c 100644 --- a/src/gallium/drivers/cell/ppu/cell_vbuf.c +++ b/src/gallium/drivers/cell/ppu/cell_vbuf.c @@ -243,7 +243,7 @@ cell_vbuf_draw(struct vbuf_render *vbr, #if 0 /* helpful for debug */ - cell_flush_int(&cell->pipe, PIPE_FLUSH_WAIT); + cell_flush_int(&cell->pipe, CELL_FLUSH_WAIT); #endif } diff --git a/src/gallium/drivers/cell/ppu/cell_vertex_fetch.c b/src/gallium/drivers/cell/ppu/cell_vertex_fetch.c index 4828a8023b..49d5443cde 100644 --- a/src/gallium/drivers/cell/ppu/cell_vertex_fetch.c +++ b/src/gallium/drivers/cell/ppu/cell_vertex_fetch.c @@ -263,7 +263,7 @@ void cell_update_vertex_fetch(struct draw_context *draw) struct cell_context *const cell = (struct cell_context *) draw->driver_private; struct spe_function *p = &cell->attrib_fetch; - unsigned function_index[PIPE_ATTRIB_MAX]; + unsigned function_index[PIPE_MAX_ATTRIBS]; unsigned unique_attr_formats; int out_ptr; int in_ptr; diff --git a/src/gallium/drivers/cell/ppu/cell_vertex_shader.c b/src/gallium/drivers/cell/ppu/cell_vertex_shader.c index f5c27852c1..f753960a0f 100644 --- a/src/gallium/drivers/cell/ppu/cell_vertex_shader.c +++ b/src/gallium/drivers/cell/ppu/cell_vertex_shader.c @@ -69,7 +69,7 @@ cell_vertex_shader_queue_flush(struct draw_context *draw) batch = cell_batch_alloc(cell, sizeof(batch[0]) + sizeof(*cf)); batch[0] = CELL_CMD_STATE_ATTRIB_FETCH; cf = (struct cell_attribute_fetch_code *) (&batch[1]); - cf->base = cell->attrib_fetch.store; + cf->base = (uint64_t) cell->attrib_fetch.store; cf->size = ROUNDUP16((unsigned)((void *) cell->attrib_fetch.csr - (void *) cell->attrib_fetch.store)); @@ -133,7 +133,7 @@ cell_vertex_shader_queue_flush(struct draw_context *draw) vs->num_elts = n; send_mbox_message(cell_global.spe_contexts[0], CELL_CMD_VS_EXECUTE); - cell_flush_int(& cell->pipe, PIPE_FLUSH_WAIT); + cell_flush_int(& cell->pipe, CELL_FLUSH_WAIT); } draw->vs.post_nr = draw->vs.queue_nr; diff --git a/src/gallium/drivers/cell/spu/spu_exec.c b/src/gallium/drivers/cell/spu/spu_exec.c index 061fbebf61..48edc62f49 100644 --- a/src/gallium/drivers/cell/spu/spu_exec.c +++ b/src/gallium/drivers/cell/spu/spu_exec.c @@ -1453,7 +1453,7 @@ exec_instruction( break; case TGSI_OPCODE_TXP: - /* Texture lookup with projection + /* Texture lookup with projection */ /* src[0] = texcoord (src[0].w = projection) */ /* src[1] = sampler unit */ exec_tex(mach, inst, TRUE, TRUE); diff --git a/src/gallium/drivers/cell/spu/spu_main.c b/src/gallium/drivers/cell/spu/spu_main.c index 0a490ab277..d7f46f8024 100644 --- a/src/gallium/drivers/cell/spu/spu_main.c +++ b/src/gallium/drivers/cell/spu/spu_main.c @@ -55,7 +55,7 @@ struct spu_global spu; struct spu_vs_context draw; -static unsigned char attribute_fetch_code_buffer[136 * PIPE_ATTRIB_MAX] +static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS] ALIGN16_ATTRIB; static unsigned char depth_stencil_code_buffer[4 * 64] @@ -64,6 +64,9 @@ static unsigned char depth_stencil_code_buffer[4 * 64] static unsigned char fb_blend_code_buffer[4 * 64] ALIGN16_ATTRIB; +static unsigned char logicop_code_buffer[4 * 64] + ALIGN16_ATTRIB; + /** * Tell the PPU that this SPU has finished copying a buffer to @@ -358,7 +361,7 @@ cmd_state_vs_array_info(const struct cell_array_info *vs_info) { const unsigned attr = vs_info->attr; - ASSERT(attr < PIPE_ATTRIB_MAX); + ASSERT(attr < PIPE_MAX_ATTRIBS); draw.vertex_fetch.src_ptr[attr] = vs_info->base; draw.vertex_fetch.pitch[attr] = vs_info->pitch; draw.vertex_fetch.size[attr] = vs_info->size; @@ -513,6 +516,22 @@ cmd_batch(uint opcode) pos += (1 + ROUNDUP8(sizeof(struct cell_attribute_fetch_code)) / 8); break; } + case CELL_CMD_STATE_LOGICOP: { + struct cell_command_logicop *code = + (struct cell_command_logicop *) &buffer[pos+1]; + + mfc_get(logicop_code_buffer, + (unsigned int) code->base, /* src */ + code->size, + TAG_BATCH_BUFFER, + 0, /* tid */ + 0 /* rid */); + wait_on_mask(1 << TAG_BATCH_BUFFER); + + spu.logicop = (logicop_func) logicop_code_buffer; + pos += (1 + ROUNDUP8(sizeof(struct cell_command_logicop)) / 8); + break; + } case CELL_CMD_FLUSH_BUFFER_RANGE: { struct cell_buffer_range *br = (struct cell_buffer_range *) &buffer[pos+1]; diff --git a/src/gallium/drivers/cell/spu/spu_main.h b/src/gallium/drivers/cell/spu/spu_main.h index 49f5d99674..c20452931a 100644 --- a/src/gallium/drivers/cell/spu/spu_main.h +++ b/src/gallium/drivers/cell/spu/spu_main.h @@ -77,9 +77,14 @@ struct spu_blend_results { typedef struct spu_blend_results (*blend_func)( qword frag_r, qword frag_g, qword frag_b, qword frag_a, qword pixel_r, qword pixel_g, qword pixel_b, qword pixel_a, - qword const_r, qword const_g, qword const_b, qword const_a, + qword const_r, qword const_g, qword const_b, qword const_a); + +typedef struct spu_blend_results (*logicop_func)( + qword pixel_r, qword pixel_g, qword pixel_b, qword pixel_a, + qword frag_r, qword frag_g, qword frag_b, qword frag_a, qword frag_mask); + struct spu_framebuffer { void *color_start; /**< addr of color surface in main memory */ void *depth_start; /**< addr of depth surface in main memory */ @@ -111,6 +116,8 @@ struct spu_global blend_func blend; qword const_blend_color[4] ALIGN16_ATTRIB; + logicop_func logicop; + struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS]; struct cell_command_texture texture; diff --git a/src/gallium/drivers/cell/spu/spu_tri.c b/src/gallium/drivers/cell/spu/spu_tri.c index e6a1ce01df..95c629a8aa 100644 --- a/src/gallium/drivers/cell/spu/spu_tri.c +++ b/src/gallium/drivers/cell/spu/spu_tri.c @@ -305,7 +305,6 @@ emit_quad( int x, int y, mask_t mask ) if (spu_extract(spu_orx(mask), 0)) { const int ix = x - setup.cliprect_minx; const int iy = y - setup.cliprect_miny; - const vector unsigned char shuffle = spu.color_shuffle; vector float colors[4]; spu.cur_ctile_status = TILE_STATUS_DIRTY; @@ -330,45 +329,53 @@ emit_quad( int x, int y, mask_t mask ) } + /* Convert fragment data from AoS to SoA format. + */ + qword soa_frag[4]; + _transpose_matrix4x4((vec_float4 *) soa_frag, colors); + /* Read the current framebuffer values. - * - * Ignore read_fb for now. In the future we can use this to avoid - * reading the framebuffer if read_fb is false and the fragment mask is - * all 0xffffffff. This is the common case, so it is probably worth - * the effort. We'll have to profile to determine whether or not the - * extra conditional branches hurt overall performance. */ - vec_float4 aos_pix[4] = { - spu_unpack_A8R8G8B8(spu.ctile.ui[iy+0][ix+0]), - spu_unpack_A8R8G8B8(spu.ctile.ui[iy+0][ix+1]), - spu_unpack_A8R8G8B8(spu.ctile.ui[iy+1][ix+0]), - spu_unpack_A8R8G8B8(spu.ctile.ui[iy+1][ix+1]), + const qword pix[4] = { + (qword) spu_splats(spu.ctile.ui[iy+0][ix+0]), + (qword) spu_splats(spu.ctile.ui[iy+0][ix+1]), + (qword) spu_splats(spu.ctile.ui[iy+1][ix+0]), + (qword) spu_splats(spu.ctile.ui[iy+1][ix+1]), }; qword soa_pix[4]; - qword soa_frag[4]; - /* Convert pixel and fragment data from AoS to SoA format. - */ - _transpose_matrix4x4((vec_float4 *) soa_pix, aos_pix); - _transpose_matrix4x4((vec_float4 *) soa_frag, colors); + if (spu.read_fb) { + /* Convert pixel data from AoS to SoA format. + */ + vec_float4 aos_pix[4] = { + spu_unpack_A8R8G8B8(spu.ctile.ui[iy+0][ix+0]), + spu_unpack_A8R8G8B8(spu.ctile.ui[iy+0][ix+1]), + spu_unpack_A8R8G8B8(spu.ctile.ui[iy+1][ix+0]), + spu_unpack_A8R8G8B8(spu.ctile.ui[iy+1][ix+1]), + }; + + _transpose_matrix4x4((vec_float4 *) soa_pix, aos_pix); + } - const struct spu_blend_results result = + + struct spu_blend_results result = (*spu.blend)(soa_frag[0], soa_frag[1], soa_frag[2], soa_frag[3], soa_pix[0], soa_pix[1], soa_pix[2], soa_pix[3], spu.const_blend_color[0], spu.const_blend_color[1], - spu.const_blend_color[2], spu.const_blend_color[3], - (qword) mask); + spu.const_blend_color[2], spu.const_blend_color[3]); /* Convert final pixel data from SoA to AoS format. */ - _transpose_matrix4x4(aos_pix, (const vec_float4 *) &result); - - spu.ctile.ui[iy+0][ix+0] = spu_pack_color_shuffle(aos_pix[0], shuffle); - spu.ctile.ui[iy+0][ix+1] = spu_pack_color_shuffle(aos_pix[1], shuffle); - spu.ctile.ui[iy+1][ix+0] = spu_pack_color_shuffle(aos_pix[2], shuffle); - spu.ctile.ui[iy+1][ix+1] = spu_pack_color_shuffle(aos_pix[3], shuffle); + result = (*spu.logicop)(pix[0], pix[1], pix[2], pix[3], + result.r, result.g, result.b, result.a, + (qword) mask); + + spu.ctile.ui[iy+0][ix+0] = spu_extract((vec_uint4) result.r, 0); + spu.ctile.ui[iy+0][ix+1] = spu_extract((vec_uint4) result.g, 0); + spu.ctile.ui[iy+1][ix+0] = spu_extract((vec_uint4) result.b, 0); + spu.ctile.ui[iy+1][ix+1] = spu_extract((vec_uint4) result.a, 0); } #endif } diff --git a/src/gallium/drivers/cell/spu/spu_vertex_shader.c b/src/gallium/drivers/cell/spu/spu_vertex_shader.c index 8363efeeb6..3119a78c06 100644 --- a/src/gallium/drivers/cell/spu/spu_vertex_shader.c +++ b/src/gallium/drivers/cell/spu/spu_vertex_shader.c @@ -86,8 +86,8 @@ run_vertex_program(struct spu_vs_context *draw, struct spu_exec_machine *machine = &draw->machine; unsigned int j; - ALIGN16_DECL(struct spu_exec_vector, inputs, PIPE_ATTRIB_MAX); - ALIGN16_DECL(struct spu_exec_vector, outputs, PIPE_ATTRIB_MAX); + ALIGN16_DECL(struct spu_exec_vector, inputs, PIPE_MAX_ATTRIBS); + ALIGN16_DECL(struct spu_exec_vector, outputs, PIPE_MAX_ATTRIBS); const float *scale = draw->viewport.scale; const float *trans = draw->viewport.translate; diff --git a/src/gallium/drivers/cell/spu/spu_vertex_shader.h b/src/gallium/drivers/cell/spu/spu_vertex_shader.h index 54a4b8d9b9..4c74f5e74d 100644 --- a/src/gallium/drivers/cell/spu/spu_vertex_shader.h +++ b/src/gallium/drivers/cell/spu/spu_vertex_shader.h @@ -16,10 +16,10 @@ struct spu_vs_context { struct pipe_viewport_state viewport; struct { - uint64_t src_ptr[PIPE_ATTRIB_MAX]; - unsigned pitch[PIPE_ATTRIB_MAX]; - unsigned size[PIPE_ATTRIB_MAX]; - unsigned code_offset[PIPE_ATTRIB_MAX]; + uint64_t src_ptr[PIPE_MAX_ATTRIBS]; + unsigned pitch[PIPE_MAX_ATTRIBS]; + unsigned size[PIPE_MAX_ATTRIBS]; + unsigned code_offset[PIPE_MAX_ATTRIBS]; unsigned nr_attrs; boolean dirty; |