summaryrefslogtreecommitdiff
path: root/src/gallium
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2008-03-21 12:54:34 +1100
committerBen Skeggs <skeggsb@gmail.com>2008-03-21 12:54:34 +1100
commit85108e5f8f3fd1ace813cb6eac6e82af4a2e2c7a (patch)
tree05d8ff1139fbf3d51a3123280a3a8fc0d2c18349 /src/gallium
parent1d9049c4df24d47446218f4032b891b817af0d00 (diff)
parentcab68957c72d6f198546a250b6fe0a74732cb3ec (diff)
Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_context.c3
-rw-r--r--src/gallium/auxiliary/util/p_debug.c18
-rw-r--r--src/gallium/auxiliary/util/u_blit.c82
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.c59
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.h16
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.c73
-rw-r--r--src/gallium/auxiliary/util/u_handle_table.c3
-rw-r--r--src/gallium/auxiliary/util/u_simple_shaders.c114
-rw-r--r--src/gallium/auxiliary/util/u_simple_shaders.h12
-rw-r--r--src/gallium/drivers/cell/common.h10
-rw-r--r--src/gallium/drivers/cell/ppu/cell_pipe_state.c11
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_derived.c13
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_emit.c21
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_per_fragment.c112
-rw-r--r--src/gallium/drivers/cell/spu/Makefile1
-rw-r--r--src/gallium/drivers/cell/spu/spu_blend.c62
-rw-r--r--src/gallium/drivers/cell/spu/spu_blend.h37
-rw-r--r--src/gallium/drivers/cell/spu/spu_main.c50
-rw-r--r--src/gallium/drivers/cell/spu/spu_main.h17
-rw-r--r--src/gallium/drivers/cell/spu/spu_tri.c59
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h2
-rw-r--r--src/gallium/drivers/softpipe/sp_prim_setup.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_stipple.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_state_derived.c4
-rw-r--r--src/gallium/drivers/softpipe/sp_state_surface.c19
-rw-r--r--src/gallium/include/pipe/p_debug.h8
-rw-r--r--src/gallium/include/pipe/p_state.h2
27 files changed, 580 insertions, 232 deletions
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index 01fe216447..4a1a6cb79c 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.c
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -496,7 +496,8 @@ void cso_restore_vertex_shader(struct cso_context *ctx)
void cso_set_framebuffer(struct cso_context *ctx,
const struct pipe_framebuffer_state *fb)
{
- if (memcmp(&ctx->fb, fb, sizeof(*fb))) {
+ /* XXX this memcmp() fails to detect buffer size changes */
+ if (1/*memcmp(&ctx->fb, fb, sizeof(*fb))*/) {
ctx->fb = *fb;
ctx->pipe->set_framebuffer_state(ctx->pipe, fb);
}
diff --git a/src/gallium/auxiliary/util/p_debug.c b/src/gallium/auxiliary/util/p_debug.c
index bd3a0221ea..c51e9e6a69 100644
--- a/src/gallium/auxiliary/util/p_debug.c
+++ b/src/gallium/auxiliary/util/p_debug.c
@@ -85,6 +85,22 @@ void debug_printf(const char *format, ...)
}
+void debug_print_blob( const char *name,
+ const void *blob,
+ unsigned size )
+{
+ const unsigned *ublob = (const unsigned *)blob;
+ unsigned i;
+
+ debug_printf("%s (%d dwords%s)\n", name, size/4,
+ size%4 ? "... plus a few bytes" : "");
+
+ for (i = 0; i < size/4; i++) {
+ debug_printf("%d:\t%08x\n", i, ublob[i]);
+ }
+}
+
+
/* TODO: implement a debug_abort that calls EngBugCheckEx on WIN32 */
@@ -240,3 +256,5 @@ debug_dump_flags(const struct debug_named_value *names,
return output;
}
+
+
diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
index d05dae3af8..28a404fd01 100644
--- a/src/gallium/auxiliary/util/u_blit.c
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -61,6 +61,9 @@ struct blit_state
/*struct pipe_viewport_state viewport;*/
struct pipe_sampler_state *vs;
struct pipe_sampler_state *fs;
+
+ struct pipe_buffer *vbuf; /**< quad vertices */
+ float vertices[4][2][4]; /**< vertex/texcoords for quad */
};
@@ -72,6 +75,7 @@ struct blit_state *
util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
{
struct blit_state *ctx;
+ uint i;
ctx = CALLOC_STRUCT(blit_state);
if (!ctx)
@@ -132,6 +136,24 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
/* fragment shader */
ctx->fs = util_make_fragment_tex_shader(pipe);
+ ctx->vbuf = pipe->winsys->buffer_create(pipe->winsys,
+ 32,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(ctx->vertices));
+ if (!ctx->vbuf) {
+ FREE(ctx);
+ ctx->pipe->delete_fs_state(ctx->pipe, ctx->fs);
+ ctx->pipe->delete_vs_state(ctx->pipe, ctx->vs);
+ return NULL;
+ }
+
+ /* init vertex data that doesn't change */
+ for (i = 0; i < 4; i++) {
+ ctx->vertices[i][0][3] = 1.0f; /* w */
+ ctx->vertices[i][1][2] = 0.0f; /* r */
+ ctx->vertices[i][1][3] = 1.0f; /* q */
+ }
+
return ctx;
}
@@ -147,11 +169,56 @@ util_destroy_blit(struct blit_state *ctx)
pipe->delete_vs_state(pipe, ctx->vs);
pipe->delete_fs_state(pipe, ctx->fs);
+ pipe->winsys->buffer_destroy(pipe->winsys, ctx->vbuf);
+
FREE(ctx);
}
/**
+ * Setup vertex data for the textured quad we'll draw.
+ * Note: y=0=top
+ */
+static void
+setup_vertex_data(struct blit_state *ctx,
+ float x0, float y0, float x1, float y1, float z)
+{
+ void *buf;
+
+ ctx->vertices[0][0][0] = x0;
+ ctx->vertices[0][0][1] = y0;
+ ctx->vertices[0][0][2] = z;
+ ctx->vertices[0][1][0] = 0.0f; /*s*/
+ ctx->vertices[0][1][1] = 0.0f; /*t*/
+
+ ctx->vertices[1][0][0] = x1;
+ ctx->vertices[1][0][1] = y0;
+ ctx->vertices[1][0][2] = z;
+ ctx->vertices[1][1][0] = 1.0f; /*s*/
+ ctx->vertices[1][1][1] = 0.0f; /*t*/
+
+ ctx->vertices[2][0][0] = x1;
+ ctx->vertices[2][0][1] = y1;
+ ctx->vertices[2][0][2] = z;
+ ctx->vertices[2][1][0] = 1.0f;
+ ctx->vertices[2][1][1] = 1.0f;
+
+ ctx->vertices[3][0][0] = x0;
+ ctx->vertices[3][0][1] = y1;
+ ctx->vertices[3][0][2] = z;
+ ctx->vertices[3][1][0] = 0.0f;
+ ctx->vertices[3][1][1] = 1.0f;
+
+ buf = ctx->pipe->winsys->buffer_map(ctx->pipe->winsys, ctx->vbuf,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ memcpy(buf, ctx->vertices, sizeof(ctx->vertices));
+
+ ctx->pipe->winsys->buffer_unmap(ctx->pipe->winsys, ctx->vbuf);
+}
+
+
+/**
* Copy pixel block from src surface to dst surface.
* Overlapping regions are acceptable.
* XXX need some control over blitting Z and/or stencil.
@@ -249,16 +316,21 @@ util_blit_pixels(struct blit_state *ctx,
/* drawing dest */
memset(&fb, 0, sizeof(fb));
+ fb.width = dst->width;
+ fb.height = dst->height;
fb.num_cbufs = 1;
fb.cbufs[0] = dst;
cso_set_framebuffer(ctx->cso, &fb);
/* draw quad */
- util_draw_texquad(pipe,
- (float)dstX0,
- (float)dstY0,
- (float)dstX1,
- (float)dstY1, z);
+ setup_vertex_data(ctx,
+ (float) dstX0, (float) dstY0,
+ (float) dstX1, (float) dstY1, z);
+
+ util_draw_vertex_buffer(ctx->pipe, ctx->vbuf,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
/* restore state we changed */
cso_restore_blend(ctx->cso);
diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c
index 79a69de633..37e8533609 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.c
+++ b/src/gallium/auxiliary/util/u_draw_quad.c
@@ -34,15 +34,51 @@
/**
+ * Draw a simple vertex buffer / primitive.
+ * Limited to float[4] vertex attribs, tightly packed.
+ */
+void
+util_draw_vertex_buffer(struct pipe_context *pipe,
+ struct pipe_buffer *vbuf,
+ uint prim_type,
+ uint num_verts,
+ uint num_attribs)
+{
+ struct pipe_vertex_buffer vbuffer;
+ struct pipe_vertex_element velement;
+ uint i;
+
+ /* tell pipe about the vertex buffer */
+ vbuffer.buffer = vbuf;
+ vbuffer.pitch = num_attribs * 4 * sizeof(float); /* vertex size */
+ vbuffer.buffer_offset = 0;
+ pipe->set_vertex_buffer(pipe, 0, &vbuffer);
+
+ /* tell pipe about the vertex attributes */
+ for (i = 0; i < num_attribs; i++) {
+ velement.src_offset = i * 4 * sizeof(float);
+ velement.vertex_buffer_index = 0;
+ velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ velement.nr_components = 4;
+ pipe->set_vertex_element(pipe, i, &velement);
+ }
+
+ /* draw */
+ pipe->draw_arrays(pipe, prim_type, 0, num_verts);
+}
+
+
+
+/**
* Draw screen-aligned textured quad.
+ * Note: this function allocs/destroys a vertex buffer and isn't especially
+ * efficient.
*/
void
util_draw_texquad(struct pipe_context *pipe,
float x0, float y0, float x1, float y1, float z)
{
struct pipe_buffer *vbuf;
- struct pipe_vertex_buffer vbuffer;
- struct pipe_vertex_element velement;
uint numAttribs = 2, vertexBytes, i, j;
float *v;
@@ -89,24 +125,7 @@ util_draw_texquad(struct pipe_context *pipe,
pipe->winsys->buffer_unmap(pipe->winsys, vbuf);
- /* tell pipe about the vertex buffer */
- vbuffer.buffer = vbuf;
- vbuffer.pitch = numAttribs * 4 * sizeof(float); /* vertex size */
- vbuffer.buffer_offset = 0;
- pipe->set_vertex_buffer(pipe, 0, &vbuffer);
-
- /* tell pipe about the vertex attributes */
- for (i = 0; i < numAttribs; i++) {
- velement.src_offset = i * 4 * sizeof(float);
- velement.vertex_buffer_index = 0;
- velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
- velement.nr_components = 4;
- pipe->set_vertex_element(pipe, i, &velement);
- }
-
- /* draw */
- pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, 4);
+ util_draw_vertex_buffer(pipe, vbuf, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
- /* XXX: do one-time */
pipe_buffer_reference(pipe->winsys, &vbuf, NULL);
}
diff --git a/src/gallium/auxiliary/util/u_draw_quad.h b/src/gallium/auxiliary/util/u_draw_quad.h
index a97f55d2ef..5b6539a99c 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.h
+++ b/src/gallium/auxiliary/util/u_draw_quad.h
@@ -29,9 +29,25 @@
#define U_DRAWQUAD_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern void
+util_draw_vertex_buffer(struct pipe_context *pipe,
+ struct pipe_buffer *vbuf,
+ uint num_attribs, uint num_verts, uint prim_type);
+
+
extern void
util_draw_texquad(struct pipe_context *pipe,
float x0, float y0, float x1, float y1, float z);
+#ifdef __cplusplus
+}
+#endif
+
+
#endif
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c
index 028b180a77..cf02f00b1b 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.c
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -64,6 +64,9 @@ struct gen_mipmap_state
/*struct pipe_viewport_state viewport;*/
struct pipe_sampler_state *vs;
struct pipe_sampler_state *fs;
+
+ struct pipe_buffer *vbuf; /**< quad vertices */
+ float vertices[4][2][4]; /**< vertex/texcoords for quad */
};
@@ -683,6 +686,7 @@ util_create_gen_mipmap(struct pipe_context *pipe,
struct cso_context *cso)
{
struct gen_mipmap_state *ctx;
+ uint i;
ctx = CALLOC_STRUCT(gen_mipmap_state);
if (!ctx)
@@ -744,10 +748,62 @@ util_create_gen_mipmap(struct pipe_context *pipe,
/* fragment shader */
ctx->fs = util_make_fragment_tex_shader(pipe);
+ ctx->vbuf = pipe->winsys->buffer_create(pipe->winsys,
+ 32,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(ctx->vertices));
+ if (!ctx->vbuf) {
+ FREE(ctx);
+ return NULL;
+ }
+
+ /* vertex data that doesn't change */
+ for (i = 0; i < 4; i++) {
+ ctx->vertices[i][0][2] = 0.0f; /* z */
+ ctx->vertices[i][0][3] = 1.0f; /* w */
+ ctx->vertices[i][1][2] = 0.0f; /* r */
+ ctx->vertices[i][1][3] = 1.0f; /* q */
+ }
+
return ctx;
}
+static void
+set_vertex_data(struct gen_mipmap_state *ctx, float width, float height)
+{
+ void *buf;
+
+ ctx->vertices[0][0][0] = 0.0f; /*x*/
+ ctx->vertices[0][0][1] = 0.0f; /*y*/
+ ctx->vertices[0][1][0] = 0.0f; /*s*/
+ ctx->vertices[0][1][1] = 0.0f; /*t*/
+
+ ctx->vertices[1][0][0] = width; /*x*/
+ ctx->vertices[1][0][1] = 0.0f; /*y*/
+ ctx->vertices[1][1][0] = 1.0f; /*s*/
+ ctx->vertices[1][1][1] = 0.0f; /*t*/
+
+ ctx->vertices[2][0][0] = width;
+ ctx->vertices[2][0][1] = height;
+ ctx->vertices[2][1][0] = 1.0f;
+ ctx->vertices[2][1][1] = 1.0f;
+
+ ctx->vertices[3][0][0] = 0.0f;
+ ctx->vertices[3][0][1] = height;
+ ctx->vertices[3][1][0] = 0.0f;
+ ctx->vertices[3][1][1] = 1.0f;
+
+ buf = ctx->pipe->winsys->buffer_map(ctx->pipe->winsys, ctx->vbuf,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ memcpy(buf, ctx->vertices, sizeof(ctx->vertices));
+
+ ctx->pipe->winsys->buffer_unmap(ctx->pipe->winsys, ctx->vbuf);
+}
+
+
+
/**
* Destroy a mipmap generation context
*/
@@ -759,6 +815,8 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
pipe->delete_vs_state(pipe, ctx->vs);
pipe->delete_fs_state(pipe, ctx->fs);
+ pipe->winsys->buffer_destroy(pipe->winsys, ctx->vbuf);
+
FREE(ctx);
}
@@ -843,6 +901,8 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
* Setup framebuffer / dest surface
*/
fb.cbufs[0] = screen->get_tex_surface(screen, pt, face, dstLevel, zslice);
+ fb.width = pt->width[dstLevel];
+ fb.height = pt->height[dstLevel];
cso_set_framebuffer(ctx->cso, &fb);
/*
@@ -863,12 +923,13 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
pipe->set_sampler_textures(pipe, 1, &pt);
/* quad coords in window coords (bypassing clipping, viewport mapping) */
- util_draw_texquad(pipe,
- 0.0F, 0.0F, /* x0, y0 */
- (float) pt->width[dstLevel], /* x1 */
- (float) pt->height[dstLevel], /* y1 */
- 0.0F); /* z */
-
+ set_vertex_data(ctx,
+ (float) pt->width[dstLevel],
+ (float) pt->height[dstLevel]);
+ util_draw_vertex_buffer(ctx->pipe, ctx->vbuf,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
pipe->flush(pipe, PIPE_FLUSH_WAIT);
diff --git a/src/gallium/auxiliary/util/u_handle_table.c b/src/gallium/auxiliary/util/u_handle_table.c
index 8b0f7fca4b..5a731a6b96 100644
--- a/src/gallium/auxiliary/util/u_handle_table.c
+++ b/src/gallium/auxiliary/util/u_handle_table.c
@@ -171,8 +171,7 @@ handle_table_set(struct handle_table *ht,
assert(ht);
assert(handle > 0);
- assert(handle <= ht->size);
- if(!handle || handle > ht->size)
+ if(!handle)
return 0;
assert(object);
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c
index 88e2ab05bd..d230ddfbeb 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.c
+++ b/src/gallium/auxiliary/util/u_simple_shaders.c
@@ -68,7 +68,7 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe,
uint ti, i;
struct pipe_shader_state shader;
- tokens = (struct tgsi_token *) malloc(maxTokens * sizeof(tokens[0]));
+ tokens = (struct tgsi_token *) MALLOC(maxTokens * sizeof(tokens[0]));
/* shader header
*/
@@ -84,16 +84,15 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe,
/* declare inputs */
for (i = 0; i < num_attribs; i++) {
-
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_INPUT;
- /*
+
decl.Declaration.Semantic = 1;
- decl.Semantic.SemanticName = TGSI_SEMANTIC_POSITION;
- decl.Semantic.SemanticIndex = 0;
- */
+ decl.Semantic.SemanticName = semantic_names[i];
+ decl.Semantic.SemanticIndex = semantic_indexes[i];
+
decl.u.DeclarationRange.First =
- decl.u.DeclarationRange.Last = 0;
+ decl.u.DeclarationRange.Last = i;
ti += tgsi_build_full_declaration(&decl,
&tokens[ti],
header,
@@ -102,19 +101,17 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe,
/* declare outputs */
for (i = 0; i < num_attribs; i++) {
-
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_OUTPUT;
decl.Declaration.Semantic = 1;
decl.Semantic.SemanticName = semantic_names[i];
decl.Semantic.SemanticIndex = semantic_indexes[i];
decl.u.DeclarationRange.First =
- decl.u.DeclarationRange.Last = 0;
+ decl.u.DeclarationRange.Last = i;
ti += tgsi_build_full_declaration(&decl,
&tokens[ti],
header,
maxTokens - ti);
-
}
/* emit MOV instructions */
@@ -173,7 +170,7 @@ util_make_fragment_tex_shader(struct pipe_context *pipe)
uint ti;
struct pipe_shader_state shader;
- tokens = (struct tgsi_token *) malloc(maxTokens * sizeof(tokens[0]));
+ tokens = (struct tgsi_token *) MALLOC(maxTokens * sizeof(tokens[0]));
/* shader header
*/
@@ -261,3 +258,98 @@ util_make_fragment_tex_shader(struct pipe_context *pipe)
return pipe->create_fs_state(pipe, &shader);
}
+
+
+
+
+/**
+ * Make simple fragment color pass-through shader.
+ */
+void *
+util_make_fragment_passthrough_shader(struct pipe_context *pipe)
+{
+ uint maxTokens = 40;
+ struct tgsi_token *tokens;
+ struct tgsi_header *header;
+ struct tgsi_processor *processor;
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+ const uint procType = TGSI_PROCESSOR_FRAGMENT;
+ uint ti;
+ struct pipe_shader_state shader;
+
+ tokens = (struct tgsi_token *) MALLOC(maxTokens * sizeof(tokens[0]));
+
+ /* shader header
+ */
+ *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
+
+ header = (struct tgsi_header *) &tokens[1];
+ *header = tgsi_build_header();
+
+ processor = (struct tgsi_processor *) &tokens[2];
+ *processor = tgsi_build_processor( procType, header );
+
+ ti = 3;
+
+ /* declare input */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_INPUT;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR;
+ decl.Semantic.SemanticIndex = 0;
+ decl.u.DeclarationRange.First =
+ decl.u.DeclarationRange.Last = 0;
+ ti += tgsi_build_full_declaration(&decl,
+ &tokens[ti],
+ header,
+ maxTokens - ti);
+
+ /* declare output */
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_OUTPUT;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR;
+ decl.Semantic.SemanticIndex = 0;
+ decl.u.DeclarationRange.First =
+ decl.u.DeclarationRange.Last = 0;
+ ti += tgsi_build_full_declaration(&decl,
+ &tokens[ti],
+ header,
+ maxTokens - ti);
+
+
+ /* MOVE out[0], in[0]; */
+ inst = tgsi_default_full_instruction();
+ inst.Instruction.Opcode = TGSI_OPCODE_MOV;
+ inst.Instruction.NumDstRegs = 1;
+ inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+ inst.FullDstRegisters[0].DstRegister.Index = 0;
+ inst.Instruction.NumSrcRegs = 1;
+ inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+ inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+ ti += tgsi_build_full_instruction(&inst,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+
+ /* END instruction */
+ inst = tgsi_default_full_instruction();
+ inst.Instruction.Opcode = TGSI_OPCODE_END;
+ inst.Instruction.NumDstRegs = 0;
+ inst.Instruction.NumSrcRegs = 0;
+ ti += tgsi_build_full_instruction(&inst,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+
+ assert(ti < maxTokens);
+
+#if 0 /*debug*/
+ tgsi_dump(tokens, 0);
+#endif
+
+ shader.tokens = tokens;
+ return pipe->create_fs_state(pipe, &shader);
+}
+
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h
index 3ef4f28801..ca219a092c 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.h
+++ b/src/gallium/auxiliary/util/u_simple_shaders.h
@@ -36,6 +36,11 @@
struct pipe_context;
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
extern void *
util_make_vertex_passthrough_shader(struct pipe_context *pipe,
uint num_attribs,
@@ -47,6 +52,13 @@ extern void *
util_make_fragment_tex_shader(struct pipe_context *pipe);
+extern void *
+util_make_fragment_passthrough_shader(struct pipe_context *pipe);
+
+
+#ifdef __cplusplus
+}
#endif
+#endif
diff --git a/src/gallium/drivers/cell/common.h b/src/gallium/drivers/cell/common.h
index fe93fd8e1a..d59e4f7036 100644
--- a/src/gallium/drivers/cell/common.h
+++ b/src/gallium/drivers/cell/common.h
@@ -115,6 +115,16 @@ struct cell_command_depth_stencil_alpha_test {
/**
+ * Upload code to perform framebuffer blend operation
+ */
+struct cell_command_blend {
+ uint64_t base; /**< Effective address of code start. */
+ unsigned size; /**< Size in bytes of test code. */
+ unsigned read_fb; /**< Flag: should framebuffer be read? */
+};
+
+
+/**
* Tell SPUs about the framebuffer size, location
*/
struct cell_command_framebuffer
diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c
index c880760e4b..86fcdcff1f 100644
--- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c
+++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c
@@ -54,14 +54,19 @@ cell_create_blend_state(struct pipe_context *pipe,
static void
-cell_bind_blend_state(struct pipe_context *pipe, void *blend)
+cell_bind_blend_state(struct pipe_context *pipe, void *state)
{
struct cell_context *cell = cell_context(pipe);
+ struct cell_blend_state *blend = (struct cell_blend_state *) state;
+
draw_flush(cell->draw);
- cell->blend = (const struct cell_blend_state *)blend;
+ if ((blend != NULL) && (blend->code.store == NULL)) {
+ cell_generate_alpha_blend(blend, &cell->blend_color);
+ }
+ cell->blend = blend;
cell->dirty |= CELL_NEW_BLEND;
}
@@ -70,7 +75,7 @@ static void
cell_delete_blend_state(struct pipe_context *pipe, void *blend)
{
struct cell_blend_state *cb = (struct cell_blend_state *) blend;
-
+
spe_release_func(& cb->code);
FREE(cb);
}
diff --git a/src/gallium/drivers/cell/ppu/cell_state_derived.c b/src/gallium/drivers/cell/ppu/cell_state_derived.c
index 5c240a55c0..5480534ad9 100644
--- a/src/gallium/drivers/cell/ppu/cell_state_derived.c
+++ b/src/gallium/drivers/cell/ppu/cell_state_derived.c
@@ -141,17 +141,8 @@ calculate_vertex_layout( struct cell_context *cell )
static void
compute_cliprect(struct cell_context *sp)
{
- unsigned surfWidth, surfHeight;
-
- if (sp->framebuffer.num_cbufs > 0) {
- surfWidth = sp->framebuffer.cbufs[0]->width;
- surfHeight = sp->framebuffer.cbufs[0]->height;
- }
- else {
- /* no surface? */
- surfWidth = sp->scissor.maxx;
- surfHeight = sp->scissor.maxy;
- }
+ uint surfWidth = sp->framebuffer.width;
+ uint surfHeight = sp->framebuffer.height;
if (sp->rasterizer->scissor) {
/* clip to scissor rect */
diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c
index 4d589bcdbf..5709b48f12 100644
--- a/src/gallium/drivers/cell/ppu/cell_state_emit.c
+++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c
@@ -60,14 +60,25 @@ cell_emit_state(struct cell_context *cell)
fb->color_format = cbuf->format;
fb->depth_start = cell->zsbuf_map;
fb->depth_format = zbuf ? zbuf->format : PIPE_FORMAT_NONE;
- fb->width = cell->framebuffer.cbufs[0]->width;
- fb->height = cell->framebuffer.cbufs[0]->height;
+ fb->width = cell->framebuffer.width;
+ fb->height = cell->framebuffer.height;
}
if (cell->dirty & CELL_NEW_BLEND) {
- emit_state_cmd(cell, CELL_CMD_STATE_BLEND,
- cell->blend,
- sizeof(struct pipe_blend_state));
+ struct cell_command_blend blend;
+
+ if (cell->blend != NULL) {
+ blend.base = (intptr_t) cell->blend->code.store;
+ blend.size = (char *) cell->blend->code.csr
+ - (char *) cell->blend->code.store;
+ blend.read_fb = TRUE;
+ } else {
+ blend.base = 0;
+ blend.size = 0;
+ blend.read_fb = FALSE;
+ }
+
+ emit_state_cmd(cell, CELL_CMD_STATE_BLEND, &blend, sizeof(blend));
}
if (cell->dirty & CELL_NEW_DEPTH_STENCIL) {
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 9c47968459..988c251e20 100644
--- a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c
+++ b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c
@@ -669,7 +669,7 @@ emit_alpha_factor_calculation(struct spe_function *f,
/**
- * \note Emits a maximum of 5 instructions
+ * \note Emits a maximum of 6 instructions
*/
static void
emit_color_factor_calculation(struct spe_function *f,
@@ -864,7 +864,11 @@ emit_blend_calculation(struct spe_function *f,
spe_il(f, src, 0);
} else if (dF == PIPE_BLENDFACTOR_ONE) {
spe_or(f, src, dst, dst);
+ } else {
+ spe_fm(f, src, dst, dst_factor);
}
+ } else if (dF == PIPE_BLENDFACTOR_ZERO) {
+ spe_fm(f, src, src, src_factor);
} else {
spe_fm(f, tmp, dst, dst_factor);
spe_fma(f, src, src, src_factor, tmp);
@@ -884,7 +888,11 @@ emit_blend_calculation(struct spe_function *f,
} else if (dF == PIPE_BLENDFACTOR_ONE) {
spe_il(f, tmp, 0);
spe_fs(f, src, tmp, dst);
+ } else {
+ spe_fm(f, src, dst, dst_factor);
}
+ } else if (dF == PIPE_BLENDFACTOR_ZERO) {
+ spe_fm(f, src, src, src_factor);
} else {
spe_fm(f, tmp, dst, dst_factor);
spe_fms(f, src, src, src_factor, tmp);
@@ -904,7 +912,11 @@ emit_blend_calculation(struct spe_function *f,
spe_il(f, src, 0);
} else if (dF == PIPE_BLENDFACTOR_ONE) {
spe_or(f, src, dst, dst);
+ } else {
+ spe_fm(f, src, dst, dst_factor);
}
+ } else if (dF == PIPE_BLENDFACTOR_ZERO) {
+ spe_fm(f, src, src, src_factor);
} else {
spe_fm(f, tmp, src, src_factor);
spe_fms(f, src, src, dst_factor, tmp);
@@ -913,12 +925,12 @@ emit_blend_calculation(struct spe_function *f,
case PIPE_BLEND_MIN:
spe_cgt(f, tmp, src, dst);
- spe_selb(f, src, dst, src, tmp);
+ spe_selb(f, src, src, dst, tmp);
break;
case PIPE_BLEND_MAX:
spe_cgt(f, tmp, src, dst);
- spe_selb(f, src, src, dst, tmp);
+ spe_selb(f, src, dst, src, tmp);
break;
default:
@@ -940,9 +952,9 @@ cell_generate_alpha_blend(struct cell_blend_state *cb,
struct spe_function *const f = &cb->code;
/* This code generates a maximum of 3 (source alpha factor)
- * + 3 (destination alpha factor) + (3 * 5) (source color factor)
- * + (3 * 5) (destination color factor) + (4 * 2) (blend equation)
- * + 4 (fragment mask) + 1 (return) = 49 instlructions. Round up to 64 to
+ * + 3 (destination alpha factor) + (3 * 6) (source color factor)
+ * + (3 * 6) (destination color factor) + (4 * 2) (blend equation)
+ * + 4 (fragment mask) + 1 (return) = 55 instlructions. Round up to 64 to
* make it a happy power-of-two.
*/
spe_init_func(f, 4 * 64);
@@ -984,16 +996,57 @@ cell_generate_alpha_blend(struct cell_blend_state *cb,
&& (b->alpha_func != PIPE_BLEND_MAX);
- sF[0] = b->rgb_src_factor;
- sF[1] = sF[0];
- sF[2] = sF[0];
- sF[3] = (b->alpha_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE)
- ? PIPE_BLENDFACTOR_ONE : b->alpha_src_factor;
+ if (b->blend_enable) {
+ sF[0] = b->rgb_src_factor;
+ sF[1] = sF[0];
+ sF[2] = sF[0];
+ switch (b->alpha_src_factor & 0x0f) {
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+ sF[3] = PIPE_BLENDFACTOR_ONE;
+ break;
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ sF[3] = b->alpha_src_factor + 1;
+ break;
+ default:
+ sF[3] = b->alpha_src_factor;
+ }
- dF[0] = b->rgb_dst_factor;
- dF[1] = dF[0];
- dF[2] = dF[0];
- dF[3] = b->rgb_dst_factor;
+ dF[0] = b->rgb_dst_factor;
+ dF[1] = dF[0];
+ dF[2] = dF[0];
+ switch (b->alpha_dst_factor & 0x0f) {
+ case PIPE_BLENDFACTOR_SRC_COLOR:
+ case PIPE_BLENDFACTOR_DST_COLOR:
+ case PIPE_BLENDFACTOR_CONST_COLOR:
+ case PIPE_BLENDFACTOR_SRC1_COLOR:
+ dF[3] = b->alpha_dst_factor + 1;
+ break;
+ default:
+ dF[3] = b->alpha_dst_factor;
+ }
+
+ func[0] = b->rgb_func;
+ func[1] = func[0];
+ func[2] = func[0];
+ func[3] = b->alpha_func;
+ } else {
+ sF[0] = PIPE_BLENDFACTOR_ONE;
+ sF[1] = PIPE_BLENDFACTOR_ONE;
+ sF[2] = PIPE_BLENDFACTOR_ONE;
+ sF[3] = PIPE_BLENDFACTOR_ONE;
+ dF[0] = PIPE_BLENDFACTOR_ZERO;
+ dF[1] = PIPE_BLENDFACTOR_ZERO;
+ dF[2] = PIPE_BLENDFACTOR_ZERO;
+ dF[3] = PIPE_BLENDFACTOR_ZERO;
+
+ func[0] = PIPE_BLEND_ADD;
+ func[1] = PIPE_BLEND_ADD;
+ func[2] = PIPE_BLEND_ADD;
+ func[3] = PIPE_BLEND_ADD;
+ }
/* If alpha writing is enabled and the alpha blend mode requires use of
@@ -1054,11 +1107,6 @@ cell_generate_alpha_blend(struct cell_blend_state *cb,
- func[0] = b->rgb_func;
- func[1] = func[0];
- func[2] = func[0];
- func[3] = b->alpha_func;
-
for (i = 0; i < 4; ++i) {
if ((b->colormask & (1U << i)) != 0) {
emit_blend_calculation(f,
@@ -1072,4 +1120,28 @@ cell_generate_alpha_blend(struct cell_blend_state *cb,
}
spe_bi(f, 0, 0, 0);
+
+#if 0
+ {
+ const uint32_t *p = f->store;
+
+ printf("# %u instructions\n", f->csr - f->store);
+ printf("# blend (%sabled)\n",
+ (cb->base.blend_enable) ? "en" : "dis");
+ printf("# RGB func / sf / df: %u %u %u\n",
+ cb->base.rgb_func,
+ cb->base.rgb_src_factor,
+ cb->base.rgb_dst_factor);
+ printf("# ALP func / sf / df: %u %u %u\n",
+ cb->base.alpha_func,
+ cb->base.alpha_src_factor,
+ cb->base.alpha_dst_factor);
+
+ printf("\t.text\n");
+ for (/* empty */; p < f->csr; p++) {
+ printf("\t.long\t0x%04x\n", *p);
+ }
+ fflush(stdout);
+ }
+#endif
}
diff --git a/src/gallium/drivers/cell/spu/Makefile b/src/gallium/drivers/cell/spu/Makefile
index 115ca8cd90..8e83610790 100644
--- a/src/gallium/drivers/cell/spu/Makefile
+++ b/src/gallium/drivers/cell/spu/Makefile
@@ -17,7 +17,6 @@ PROG_SPU_EMBED_O = $(PROG)_spu-embed.o
SOURCES = \
spu_main.c \
- spu_blend.c \
spu_dcache.c \
spu_per_fragment_op.c \
spu_render.c \
diff --git a/src/gallium/drivers/cell/spu/spu_blend.c b/src/gallium/drivers/cell/spu/spu_blend.c
deleted file mode 100644
index 23ec0eeb45..0000000000
--- a/src/gallium/drivers/cell/spu/spu_blend.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-
-#include "spu_main.h"
-#include "spu_blend.h"
-#include "spu_colorpack.h"
-
-
-void
-blend_quad(uint itx, uint ity, vector float colors[4])
-{
- /* simple SRC_ALPHA, ONE_MINUS_SRC_ALPHA blending */
- vector float fbc00 = spu_unpack_color(spu.ctile.ui[ity][itx]);
- vector float fbc01 = spu_unpack_color(spu.ctile.ui[ity][itx+1]);
- vector float fbc10 = spu_unpack_color(spu.ctile.ui[ity+1][itx]);
- vector float fbc11 = spu_unpack_color(spu.ctile.ui[ity+1][itx+1]);
-
- vector float alpha00 = spu_splats(spu_extract(colors[0], 3));
- vector float alpha01 = spu_splats(spu_extract(colors[1], 3));
- vector float alpha10 = spu_splats(spu_extract(colors[2], 3));
- vector float alpha11 = spu_splats(spu_extract(colors[3], 3));
-
- vector float one_minus_alpha00 = spu_sub(spu_splats(1.0f), alpha00);
- vector float one_minus_alpha01 = spu_sub(spu_splats(1.0f), alpha01);
- vector float one_minus_alpha10 = spu_sub(spu_splats(1.0f), alpha10);
- vector float one_minus_alpha11 = spu_sub(spu_splats(1.0f), alpha11);
-
- colors[0] = spu_add(spu_mul(colors[0], alpha00),
- spu_mul(fbc00, one_minus_alpha00));
- colors[1] = spu_add(spu_mul(colors[1], alpha01),
- spu_mul(fbc01, one_minus_alpha01));
- colors[2] = spu_add(spu_mul(colors[2], alpha10),
- spu_mul(fbc10, one_minus_alpha10));
- colors[3] = spu_add(spu_mul(colors[3], alpha11),
- spu_mul(fbc11, one_minus_alpha11));
-}
-
diff --git a/src/gallium/drivers/cell/spu/spu_blend.h b/src/gallium/drivers/cell/spu/spu_blend.h
deleted file mode 100644
index 2b594b578b..0000000000
--- a/src/gallium/drivers/cell/spu/spu_blend.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
- *
- **************************************************************************/
-
-
-#ifndef SPU_BLEND_H
-#define SPU_BLEND_H
-
-
-extern void
-blend_quad(uint itx, uint ity, vector float colors[4]);
-
-
-#endif /* SPU_BLEND_H */
diff --git a/src/gallium/drivers/cell/spu/spu_main.c b/src/gallium/drivers/cell/spu/spu_main.c
index 937962285d..41bebf5362 100644
--- a/src/gallium/drivers/cell/spu/spu_main.c
+++ b/src/gallium/drivers/cell/spu/spu_main.c
@@ -61,6 +61,25 @@ static unsigned char attribute_fetch_code_buffer[136 * PIPE_ATTRIB_MAX]
static unsigned char depth_stencil_code_buffer[4 * 64]
ALIGN16_ATTRIB;
+static unsigned char fb_blend_code_buffer[4 * 64]
+ ALIGN16_ATTRIB;
+
+static struct spu_blend_results
+default_blend(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 frag_mask)
+{
+ struct spu_blend_results result;
+
+ result.r = si_selb(pixel_r, frag_r, frag_mask);
+ result.g = si_selb(pixel_g, frag_g, frag_mask);
+ result.b = si_selb(pixel_b, frag_b, frag_mask);
+ result.a = si_selb(pixel_a, frag_a, frag_mask);
+
+ return result;
+}
+
+
/**
* Tell the PPU that this SPU has finished copying a buffer to
* local store and that it may be reused by the PPU.
@@ -246,14 +265,31 @@ cmd_state_framebuffer(const struct cell_command_framebuffer *cmd)
static void
-cmd_state_blend(const struct pipe_blend_state *state)
+cmd_state_blend(const struct cell_command_blend *state)
{
if (Debug)
printf("SPU %u: BLEND: enabled %d\n",
spu.init.id,
- state->blend_enable);
+ (state->size != 0));
+
+ ASSERT_ALIGN16(state->base);
- memcpy(&spu.blend, state, sizeof(*state));
+ if (state->size != 0) {
+ mfc_get(fb_blend_code_buffer,
+ (unsigned int) state->base, /* src */
+ ROUNDUP16(state->size),
+ TAG_BATCH_BUFFER,
+ 0, /* tid */
+ 0 /* rid */);
+ wait_on_mask(1 << TAG_BATCH_BUFFER);
+ spu.blend = (blend_func) fb_blend_code_buffer;
+ spu.read_fb = state->read_fb;
+ } else {
+ /* If there is no code, use the default;
+ */
+ spu.blend = default_blend;
+ spu.read_fb = FALSE;
+ }
}
@@ -441,9 +477,8 @@ cmd_batch(uint opcode)
pos += 1;
break;
case CELL_CMD_STATE_BLEND:
- cmd_state_blend((struct pipe_blend_state *)
- &buffer[pos+1]);
- pos += (1 + ROUNDUP8(sizeof(struct pipe_blend_state)) / 8);
+ cmd_state_blend((struct cell_command_blend *) &buffer[pos+1]);
+ pos += (1 + ROUNDUP8(sizeof(struct cell_command_blend)) / 8);
break;
case CELL_CMD_STATE_DEPTH_STENCIL:
cmd_state_depth_stencil((struct cell_command_depth_stencil_alpha_test *)
@@ -587,6 +622,9 @@ one_time_init(void)
memset(spu.ctile_status, TILE_STATUS_DEFINED, sizeof(spu.ctile_status));
memset(spu.ztile_status, TILE_STATUS_DEFINED, sizeof(spu.ztile_status));
invalidate_tex_cache();
+
+ spu.blend = default_blend;
+ spu.read_fb = FALSE;
}
diff --git a/src/gallium/drivers/cell/spu/spu_main.h b/src/gallium/drivers/cell/spu/spu_main.h
index 444e218645..56d0968676 100644
--- a/src/gallium/drivers/cell/spu/spu_main.h
+++ b/src/gallium/drivers/cell/spu/spu_main.h
@@ -67,6 +67,18 @@ typedef struct spu_frag_test_results (*frag_test_func)(qword frag_mask,
qword frag_alpha, qword facing);
+struct spu_blend_results {
+ qword r;
+ qword g;
+ qword b;
+ qword a;
+};
+
+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 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 */
@@ -93,7 +105,10 @@ struct spu_global
boolean read_depth;
boolean read_stencil;
frag_test_func frag_test;
- struct pipe_blend_state blend;
+
+ boolean read_fb;
+ blend_func blend;
+
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 81823f2463..c4272d6e93 100644
--- a/src/gallium/drivers/cell/spu/spu_tri.c
+++ b/src/gallium/drivers/cell/spu/spu_tri.c
@@ -29,10 +29,10 @@
* Triangle rendering within a tile.
*/
+#include <transpose_matrix4x4.h>
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
#include "pipe/p_util.h"
-#include "spu_blend.h"
#include "spu_colorpack.h"
#include "spu_main.h"
#include "spu_texture.h"
@@ -261,6 +261,9 @@ do_depth_test(int x, int y, mask_t quadmask)
float4 zvals;
mask_t mask;
+ if (spu.fb.depth_format == PIPE_FORMAT_NONE)
+ return quadmask;
+
zvals.v = eval_z((float) x, (float) y);
mask = (mask_t) spu_do_depth_stencil(x - setup.cliprect_minx,
@@ -326,27 +329,45 @@ emit_quad( int x, int y, mask_t mask )
eval_coeff(1, (float) x, (float) y, colors);
}
-#if 1
- if (spu.blend.blend_enable)
- blend_quad(ix % TILE_SIZE, iy % TILE_SIZE, colors);
-#endif
- if (spu_extract(mask, 0))
- spu.ctile.ui[iy][ix] = spu_pack_color_shuffle(colors[0], shuffle);
- if (spu_extract(mask, 1))
- spu.ctile.ui[iy][ix+1] = spu_pack_color_shuffle(colors[1], shuffle);
- if (spu_extract(mask, 2))
- spu.ctile.ui[iy+1][ix] = spu_pack_color_shuffle(colors[2], shuffle);
- if (spu_extract(mask, 3))
- spu.ctile.ui[iy+1][ix+1] = spu_pack_color_shuffle(colors[3], shuffle);
+ /* 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]),
+ };
-#if 0
- /* SIMD_Z with swizzled color buffer (someday) */
- vector unsigned int uicolors = *((vector unsigned int *) &colors);
- spu.ctile.ui4[iy/2][ix/2] = spu_sel(spu.ctile.ui4[iy/2][ix/2], uicolors, mask);
-#endif
- }
+ 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);
+
+ const 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],
+ (qword) mask);
+
+
+ /* 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);
+ }
#endif
}
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
index 31d7062dcc..19e6cfaf02 100644
--- a/src/gallium/drivers/softpipe/sp_context.h
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -84,8 +84,6 @@ struct softpipe_context {
unsigned num_samplers;
unsigned num_textures;
- uint fb_width, fb_height;
-
/* Counter for occlusion queries. Note this supports overlapping
* queries.
*/
diff --git a/src/gallium/drivers/softpipe/sp_prim_setup.c b/src/gallium/drivers/softpipe/sp_prim_setup.c
index f2d6043e2e..6a81e4d8cc 100644
--- a/src/gallium/drivers/softpipe/sp_prim_setup.c
+++ b/src/gallium/drivers/softpipe/sp_prim_setup.c
@@ -485,7 +485,7 @@ setup_fragcoord_coeff(struct setup_stage *setup, uint slot)
/*Y*/
if (setup->softpipe->rasterizer->origin_lower_left) {
/* y=0=bottom */
- const int winHeight = setup->softpipe->fb_height;
+ const int winHeight = setup->softpipe->framebuffer.height;
setup->coef[slot].a0[1] = (float) (winHeight - 1);
setup->coef[slot].dady[1] = -1.0;
}
diff --git a/src/gallium/drivers/softpipe/sp_quad_stipple.c b/src/gallium/drivers/softpipe/sp_quad_stipple.c
index 9a39249576..f1e9b80e09 100644
--- a/src/gallium/drivers/softpipe/sp_quad_stipple.c
+++ b/src/gallium/drivers/softpipe/sp_quad_stipple.c
@@ -25,7 +25,7 @@ stipple_quad(struct quad_stage *qs, struct quad_header *quad)
int y0, y1;
uint stipple0, stipple1;
if (softpipe->rasterizer->origin_lower_left) {
- y0 = softpipe->fb_height - 1 - quad->y0;
+ y0 = softpipe->framebuffer.height - 1 - quad->y0;
y1 = y0 - 1;
}
else {
diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c
index 53b2056b8a..14abb20eeb 100644
--- a/src/gallium/drivers/softpipe/sp_state_derived.c
+++ b/src/gallium/drivers/softpipe/sp_state_derived.c
@@ -171,8 +171,8 @@ softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe)
static void
compute_cliprect(struct softpipe_context *sp)
{
- uint surfWidth = sp->fb_width;
- uint surfHeight = sp->fb_height;
+ uint surfWidth = sp->framebuffer.width;
+ uint surfHeight = sp->framebuffer.height;
if (sp->rasterizer->scissor) {
/* clip to scissor rect */
diff --git a/src/gallium/drivers/softpipe/sp_state_surface.c b/src/gallium/drivers/softpipe/sp_state_surface.c
index 2f55684464..ba8c9eece7 100644
--- a/src/gallium/drivers/softpipe/sp_state_surface.c
+++ b/src/gallium/drivers/softpipe/sp_state_surface.c
@@ -48,9 +48,6 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe,
struct softpipe_context *sp = softpipe_context(pipe);
uint i;
- /* updated below */
- sp->fb_width = sp->fb_height = 0;
-
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
/* check if changing cbuf */
if (sp->framebuffer.cbufs[i] != fb->cbufs[i]) {
@@ -63,10 +60,6 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe,
/* update cache */
sp_tile_cache_set_surface(sp->cbuf_cache[i], fb->cbufs[i]);
}
- if (fb->cbufs[i]) {
- sp->fb_width = fb->cbufs[i]->width;
- sp->fb_height = fb->cbufs[i]->height;
- }
}
sp->framebuffer.num_cbufs = fb->num_cbufs;
@@ -81,11 +74,6 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe,
/* update cache */
sp_tile_cache_set_surface(sp->zsbuf_cache, fb->zsbuf);
-
- if (!sp->fb_width && fb->zsbuf) {
- sp->fb_width = fb->zsbuf->width;
- sp->fb_height = fb->zsbuf->height;
- }
}
#if 0
@@ -113,9 +101,8 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe,
}
#endif
+ sp->framebuffer.width = fb->width;
+ sp->framebuffer.height = fb->height;
+
sp->dirty |= SP_NEW_FRAMEBUFFER;
}
-
-
-
-
diff --git a/src/gallium/include/pipe/p_debug.h b/src/gallium/include/pipe/p_debug.h
index e924c1ef60..14f8056924 100644
--- a/src/gallium/include/pipe/p_debug.h
+++ b/src/gallium/include/pipe/p_debug.h
@@ -73,6 +73,14 @@ extern "C" {
*/
void debug_printf(const char *format, ...);
+
+/* Dump a blob in hex to the same place that debug_printf sends its
+ * messages:
+ */
+void debug_print_blob( const char *name,
+ const void *blob,
+ unsigned size );
+
/**
* @sa debug_printf
*/
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 5791a10119..3e531c4da4 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -220,6 +220,8 @@ struct pipe_blend_color
struct pipe_framebuffer_state
{
+ unsigned width, height;
+
/** multiple colorbuffers for multiple render targets */
unsigned num_cbufs;
struct pipe_surface *cbufs[PIPE_MAX_COLOR_BUFS];