summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <[email protected]>2008-03-21 12:54:34 +1100
committerBen Skeggs <[email protected]>2008-03-21 12:54:34 +1100
commit85108e5f8f3fd1ace813cb6eac6e82af4a2e2c7a (patch)
tree05d8ff1139fbf3d51a3123280a3a8fc0d2c18349
parent1d9049c4df24d47446218f4032b891b817af0d00 (diff)
parentcab68957c72d6f198546a250b6fe0a74732cb3ec (diff)
Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
-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_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
-rw-r--r--src/mesa/sources1
-rw-r--r--src/mesa/state_tracker/st_atom_framebuffer.c3
-rw-r--r--src/mesa/state_tracker/st_atom_texture.c5
-rw-r--r--src/mesa/state_tracker/st_cb_bitmap.c524
-rw-r--r--src/mesa/state_tracker/st_cb_bitmap.h (renamed from src/gallium/drivers/cell/spu/spu_blend.h)16
-rw-r--r--src/mesa/state_tracker/st_cb_blit.c13
-rw-r--r--src/mesa/state_tracker/st_cb_clear.c221
-rw-r--r--src/mesa/state_tracker/st_cb_clear.h4
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c295
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.h4
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c13
-rw-r--r--src/mesa/state_tracker/st_context.c8
-rw-r--r--src/mesa/state_tracker/st_context.h12
-rw-r--r--src/mesa/state_tracker/st_debug.c3
40 files changed, 1250 insertions, 647 deletions
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index 01fe2164478..4a1a6cb79c2 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 bd3a0221eaa..c51e9e6a692 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 d05dae3af8f..28a404fd01f 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 79a69de633d..37e85336091 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 a97f55d2efd..5b6539a99ca 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 028b180a777..cf02f00b1b7 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 8b0f7fca4b1..5a731a6b963 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 88e2ab05bd0..d230ddfbebc 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 3ef4f288018..ca219a092c7 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 fe93fd8e1a2..d59e4f7036e 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 c880760e4bd..86fcdcff1f6 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 5c240a55c0b..5480534ad90 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 4d589bcdbf9..5709b48f129 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 9c479684596..988c251e205 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 115ca8cd901..8e83610790e 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 23ec0eeb451..00000000000
--- 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_main.c b/src/gallium/drivers/cell/spu/spu_main.c
index 937962285d0..41bebf5362b 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 444e2186452..56d0968676b 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 81823f24633..c4272d6e93c 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 31d7062dcc0..19e6cfaf02e 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 f2d6043e2ed..6a81e4d8cc2 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 9a39249576b..f1e9b80e09a 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 53b2056b8a6..14abb20eeb2 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 2f556844644..ba8c9eece72 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 e924c1ef606..14f8056924d 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 5791a10119c..3e531c4da48 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];
diff --git a/src/mesa/sources b/src/mesa/sources
index 287af7121aa..d109dce5bcc 100644
--- a/src/mesa/sources
+++ b/src/mesa/sources
@@ -172,6 +172,7 @@ STATETRACKER_SOURCES = \
state_tracker/st_atom_texture.c \
state_tracker/st_atom_viewport.c \
state_tracker/st_cb_accum.c \
+ state_tracker/st_cb_bitmap.c \
state_tracker/st_cb_blit.c \
state_tracker/st_cb_bufferobjects.c \
state_tracker/st_cb_clear.c \
diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c
index 43259c3ecb1..02573af8f0a 100644
--- a/src/mesa/state_tracker/st_atom_framebuffer.c
+++ b/src/mesa/state_tracker/st_atom_framebuffer.c
@@ -52,6 +52,9 @@ update_framebuffer_state( struct st_context *st )
memset(framebuffer, 0, sizeof(*framebuffer));
+ framebuffer->width = fb->Width;
+ framebuffer->height = fb->Height;
+
/* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state
* to determine which surfaces to draw to
*/
diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c
index 2a711e513df..9aef30f4566 100644
--- a/src/mesa/state_tracker/st_atom_texture.c
+++ b/src/mesa/state_tracker/st_atom_texture.c
@@ -64,7 +64,10 @@ update_textures(struct st_context *st)
GLboolean flush, retval;
retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush);
- /* XXX retval indicates whether there's a texture border */
+ if (!retval) {
+ /* out of mem */
+ continue;
+ }
st->state.num_textures = unit + 1;
}
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
new file mode 100644
index 00000000000..33256196bb5
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -0,0 +1,524 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/texformat.h"
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_atom_constbuf.h"
+#include "st_program.h"
+#include "st_cb_bitmap.h"
+#include "st_mesa_to_tgsi.h"
+#include "st_texture.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_winsys.h"
+#include "util/p_tile.h"
+#include "util/u_draw_quad.h"
+#include "util/u_simple_shaders.h"
+#include "shader/prog_instruction.h"
+#include "cso_cache/cso_context.h"
+
+
+
+/**
+ * Make fragment program for glBitmap:
+ * Sample the texture and kill the fragment if the bit is 0.
+ * This program will be combined with the user's fragment program.
+ */
+static struct st_fragment_program *
+make_bitmap_fragment_program(GLcontext *ctx)
+{
+ struct st_fragment_program *stfp;
+ struct gl_program *p;
+ GLuint ic = 0;
+
+ p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+ if (!p)
+ return NULL;
+
+ p->NumInstructions = 5;
+
+ p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
+ if (!p->Instructions) {
+ ctx->Driver.DeleteProgram(ctx, p);
+ return NULL;
+ }
+ _mesa_init_instructions(p->Instructions, p->NumInstructions);
+
+ /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
+ p->Instructions[ic].Opcode = OPCODE_TEX;
+ p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
+ p->Instructions[ic].DstReg.Index = 0;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
+ p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
+ p->Instructions[ic].TexSrcUnit = 0;
+ p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+
+ /* SWZ tmp0.x, tmp0.x, 1111; # tmp0.x = 1.0 */
+ p->Instructions[ic].Opcode = OPCODE_SWZ;
+ p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
+ p->Instructions[ic].DstReg.Index = 0;
+ p->Instructions[ic].DstReg.WriteMask = WRITEMASK_X;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ p->Instructions[ic].SrcReg[0].Index = 0;
+ p->Instructions[ic].SrcReg[0].Swizzle
+ = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE );
+ ic++;
+
+ /* SUB tmp0, tmp0.wwww, tmp0.xxxx; # tmp0.w -= 1 */
+ p->Instructions[ic].Opcode = OPCODE_SUB;
+ p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
+ p->Instructions[ic].DstReg.Index = 0;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ p->Instructions[ic].SrcReg[0].Index = 0;
+ p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_WWWW;
+ p->Instructions[ic].SrcReg[1].File = PROGRAM_TEMPORARY;
+ p->Instructions[ic].SrcReg[1].Index = 0;
+ p->Instructions[ic].SrcReg[1].Swizzle = SWIZZLE_XXXX; /* 1.0 */
+ ic++;
+
+ /* KIL if tmp0 < 0 */
+ p->Instructions[ic].Opcode = OPCODE_KIL;
+ p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ p->Instructions[ic].SrcReg[0].Index = 0;
+ ic++;
+
+ /* END; */
+ p->Instructions[ic++].Opcode = OPCODE_END;
+
+ assert(ic == p->NumInstructions);
+
+ p->InputsRead = FRAG_BIT_TEX0;
+ p->OutputsWritten = 0x0;
+
+ stfp = (struct st_fragment_program *) p;
+ stfp->Base.UsesKill = GL_TRUE;
+ st_translate_fragment_program(ctx->st, stfp, NULL);
+
+ return stfp;
+}
+
+
+/**
+ * Combine basic bitmap fragment program with the user-defined program.
+ */
+static struct st_fragment_program *
+combined_bitmap_fragment_program(GLcontext *ctx)
+{
+ struct st_context *st = ctx->st;
+ struct st_fragment_program *stfp;
+
+ if (!st->bitmap.program) {
+ /* create the basic bitmap fragment program */
+ st->bitmap.program = make_bitmap_fragment_program(ctx);
+ }
+
+ if (st->bitmap.user_prog_sn == st->fp->serialNo) {
+ /* re-use */
+ stfp = st->bitmap.combined_prog;
+ }
+ else {
+ /* Concatenate the bitmap program with the current user-defined program.
+ */
+ stfp = (struct st_fragment_program *)
+ _mesa_combine_programs(ctx,
+ &st->bitmap.program->Base.Base,
+ &st->fp->Base.Base);
+
+#if 0
+ {
+ struct gl_program *p = &stfp->Base.Base;
+ printf("Combined bitmap program:\n");
+ _mesa_print_program(p);
+ printf("InputsRead: 0x%x\n", p->InputsRead);
+ printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
+ _mesa_print_parameter_list(p->Parameters);
+ }
+#endif
+
+ /* translate to TGSI tokens */
+ st_translate_fragment_program(st, stfp, NULL);
+
+ /* save new program, update serial numbers */
+ st->bitmap.user_prog_sn = st->fp->serialNo;
+ st->bitmap.combined_prog = stfp;
+ }
+
+ /* Ideally we'd have updated the pipe constants during the normal
+ * st/atom mechanism. But we can't since this is specific to glBitmap.
+ */
+ st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
+
+ return stfp;
+}
+
+
+
+/**
+ * Create a texture which represents a bitmap image.
+ */
+static struct pipe_texture *
+make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_surface *surface;
+ uint format = 0, cpp, comp;
+ ubyte *dest;
+ struct pipe_texture *pt;
+ int row, col;
+
+ /* find a texture format we know */
+ if (screen->is_format_supported( screen, PIPE_FORMAT_U_I8, PIPE_TEXTURE )) {
+ format = PIPE_FORMAT_U_I8;
+ cpp = 1;
+ comp = 0;
+ }
+ else if (screen->is_format_supported( screen, PIPE_FORMAT_A8R8G8B8_UNORM, PIPE_TEXTURE )) {
+ format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ cpp = 4;
+ comp = 3; /* alpha channel */ /*XXX little-endian dependency */
+ }
+ else {
+ /* XXX support more formats */
+ assert( 0 );
+ }
+
+ /**
+ * Create a texture.
+ */
+ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, width, height,
+ 1, 0);
+ if (!pt)
+ return NULL;
+
+ if (unpack->BufferObj && unpack->BufferObj->Name) {
+ /*
+ pt->region = buffer_object_region(unpack->BufferObj);
+ */
+ printf("st_Bitmap (sourcing from PBO not implemented yet)\n");
+ }
+
+ surface = screen->get_tex_surface(screen, pt, 0, 0, 0);
+
+ /* map texture surface */
+ dest = pipe_surface_map(surface);
+
+ /* Put image into texture surface.
+ * Note that the image is actually going to be upside down in
+ * the texture. We deal with that with texcoords.
+ */
+
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
+ bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
+ ubyte *destRow = dest + row * surface->pitch * cpp;
+
+ if (unpack->LsbFirst) {
+ /* Lsb first */
+ GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
+ for (col = 0; col < width; col++) {
+
+ /* set texel to 255 if bit is set */
+ destRow[comp] = (*src & mask) ? 255 : 0;
+ destRow += cpp;
+
+ if (mask == 128U) {
+ src++;
+ mask = 1U;
+ }
+ else {
+ mask = mask << 1;
+ }
+ }
+
+ /* get ready for next row */
+ if (mask != 1)
+ src++;
+ }
+ else {
+ /* Msb first */
+ GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
+ for (col = 0; col < width; col++) {
+
+ /* set texel to 255 if bit is set */
+ destRow[comp] =(*src & mask) ? 255 : 0;
+ destRow += cpp;
+
+ if (mask == 1U) {
+ src++;
+ mask = 128U;
+ }
+ else {
+ mask = mask >> 1;
+ }
+ }
+
+ /* get ready for next row */
+ if (mask != 128)
+ src++;
+ }
+
+ } /* row */
+
+ /* Release surface */
+ pipe_surface_unmap(surface);
+ pipe_surface_reference(&surface, NULL);
+ pipe->texture_update(pipe, pt, 0, 0x1);
+
+ pt->format = format;
+
+ return pt;
+}
+
+
+static void
+setup_bitmap_vertex_data(struct st_context *st,
+ int x, int y, int width, int height,
+ float z, const float color[4])
+{
+ struct pipe_context *pipe = st->pipe;
+ const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+ const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
+ const GLfloat x0 = x;
+ const GLfloat x1 = x + width;
+ const GLfloat y0 = invert ? (fb->Height - y - height) : y;
+ const GLfloat y1 = invert ? (y0 + height) : y + height;
+ const GLfloat bias = st->bitmap_texcoord_bias;
+ const GLfloat xBias = bias / (x1-x0);
+ const GLfloat yBias = bias / (y1-y0);
+ const GLfloat sLeft = 0.0 + xBias, sRight = 1.0 + xBias;
+ const GLfloat tTop = 1.0 - yBias, tBot = 1.0 - tTop - yBias;
+ GLuint i;
+ void *buf;
+
+ if (!st->bitmap.vbuf) {
+ st->bitmap.vbuf = pipe->winsys->buffer_create(pipe->winsys, 32,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(st->bitmap.vertices));
+ }
+
+ /* positions, texcoords */
+ st->bitmap.vertices[0][0][0] = x0;
+ st->bitmap.vertices[0][0][1] = y0;
+ st->bitmap.vertices[0][2][0] = sLeft;
+ st->bitmap.vertices[0][2][1] = tTop;
+
+ st->bitmap.vertices[1][0][0] = x1;
+ st->bitmap.vertices[1][0][1] = y0;
+ st->bitmap.vertices[1][2][0] = sRight;
+ st->bitmap.vertices[1][2][1] = tTop;
+
+ st->bitmap.vertices[2][0][0] = x1;
+ st->bitmap.vertices[2][0][1] = y1;
+ st->bitmap.vertices[2][2][0] = sRight;
+ st->bitmap.vertices[2][2][1] = tBot;
+
+ st->bitmap.vertices[3][0][0] = x0;
+ st->bitmap.vertices[3][0][1] = y1;
+ st->bitmap.vertices[3][2][0] = sLeft;
+ st->bitmap.vertices[3][2][1] = tBot;
+
+ /* same for all verts: */
+ for (i = 0; i < 4; i++) {
+ st->bitmap.vertices[i][0][2] = z;
+ st->bitmap.vertices[i][0][3] = 1.0;
+ st->bitmap.vertices[i][1][0] = color[0];
+ st->bitmap.vertices[i][1][1] = color[1];
+ st->bitmap.vertices[i][1][2] = color[2];
+ st->bitmap.vertices[i][1][3] = color[3];
+ st->bitmap.vertices[i][2][2] = 0.0; /*R*/
+ st->bitmap.vertices[i][2][3] = 1.0; /*Q*/
+ }
+
+ /* put vertex data into vbuf */
+ buf = pipe->winsys->buffer_map(pipe->winsys, st->bitmap.vbuf,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ memcpy(buf, st->bitmap.vertices, sizeof(st->bitmap.vertices));
+ pipe->winsys->buffer_unmap(pipe->winsys, st->bitmap.vbuf);
+}
+
+
+
+/**
+ * Render a glBitmap by drawing a textured quad
+ */
+static void
+draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
+ GLsizei width, GLsizei height,
+ struct pipe_texture *pt,
+ struct st_fragment_program *stfp)
+{
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct cso_context *cso = ctx->st->cso_context;
+ GLuint maxSize;
+
+ /* limit checks */
+ /* XXX if DrawPixels image is larger than max texture size, break
+ * it up into chunks.
+ */
+ maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
+ assert(width <= maxSize);
+ assert(height <= maxSize);
+
+ cso_save_rasterizer(cso);
+ //cso_save_viewport(cso);
+
+ /* rasterizer state: just scissor */
+ {
+ struct pipe_rasterizer_state rasterizer;
+ memset(&rasterizer, 0, sizeof(rasterizer));
+ if (ctx->Scissor.Enabled)
+ rasterizer.scissor = 1;
+ rasterizer.bypass_clipping = 1;
+
+ cso_set_rasterizer(cso, &rasterizer);
+ }
+
+ /* fragment shader state: TEX lookup program */
+ pipe->bind_fs_state(pipe, stfp->driver_shader);
+
+ /* vertex shader state: position + texcoord pass-through */
+ pipe->bind_vs_state(pipe, st->bitmap.vs);
+
+ /* sampler / texture state */
+ {
+ struct pipe_sampler_state sampler;
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP;
+ sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ sampler.normalized_coords = 1;
+
+ cso_single_sampler(cso, 0, &sampler);
+ cso_single_sampler_done(cso);
+
+ pipe->set_sampler_textures(pipe, 1, &pt);
+ }
+
+ /* draw textured quad */
+ setup_bitmap_vertex_data(st, x, y, width, height,
+ ctx->Current.RasterPos[2],
+ ctx->Current.RasterColor);
+
+ util_draw_vertex_buffer(pipe, st->bitmap.vbuf,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 3); /* attribs/vert */
+
+
+ /* restore state */
+ cso_restore_rasterizer(cso);
+ cso_restore_samplers(cso);
+ //cso_restore_viewport(cso);
+ /* shaders don't go through cso yet */
+ pipe->bind_fs_state(pipe, st->fp->driver_shader);
+ pipe->bind_vs_state(pipe, st->vp->driver_shader);
+
+ pipe->set_sampler_textures(pipe, ctx->st->state.num_textures,
+ ctx->st->state.sampler_texture);
+}
+
+
+
+static void
+st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
+{
+ struct st_fragment_program *stfp;
+ struct st_context *st = ctx->st;
+ struct pipe_texture *pt;
+
+ stfp = combined_bitmap_fragment_program(ctx);
+
+ if (!st->bitmap.vs) {
+ /* create pass-through vertex shader now */
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_COLOR,
+ TGSI_SEMANTIC_GENERIC };
+ const uint semantic_indexes[] = { 0, 0, 0 };
+ st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3,
+ semantic_names,
+ semantic_indexes);
+ }
+
+ st_validate_state(st);
+
+ pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
+ if (pt) {
+ draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
+ width, height,
+ pt, stfp);
+ pipe_texture_reference(&pt, NULL);
+ }
+}
+
+
+
+void st_init_bitmap_functions(struct dd_function_table *functions)
+{
+ functions->Bitmap = st_Bitmap;
+}
+
+
+void
+st_destroy_bitmap(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+
+ /* XXX free frag shader state */
+
+ if (st->bitmap.vs) {
+ pipe->delete_vs_state(pipe, st->bitmap.vs);
+ st->bitmap.vs = NULL;
+ }
+ if (st->bitmap.vbuf) {
+ pipe->winsys->buffer_destroy(pipe->winsys, st->bitmap.vbuf);
+ st->bitmap.vbuf = NULL;
+ }
+}
+
diff --git a/src/gallium/drivers/cell/spu/spu_blend.h b/src/mesa/state_tracker/st_cb_bitmap.h
index 2b594b578b4..ac19e0ebb12 100644
--- a/src/gallium/drivers/cell/spu/spu_blend.h
+++ b/src/mesa/state_tracker/st_cb_bitmap.h
@@ -1,8 +1,8 @@
/**************************************************************************
*
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2007 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
@@ -26,12 +26,16 @@
**************************************************************************/
-#ifndef SPU_BLEND_H
-#define SPU_BLEND_H
+#ifndef ST_CB_BITMAP_H
+#define ST_CB_BITMAP_H
+
+
+extern void
+st_init_bitmap_functions(struct dd_function_table *functions);
extern void
-blend_quad(uint itx, uint ity, vector float colors[4]);
+st_destroy_bitmap(struct st_context *st);
-#endif /* SPU_BLEND_H */
+#endif /* ST_CB_BITMAP_H */
diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c
index 64314a5078f..63211d8b66e 100644
--- a/src/mesa/state_tracker/st_cb_blit.c
+++ b/src/mesa/state_tracker/st_cb_blit.c
@@ -85,11 +85,14 @@ st_BlitFramebuffer(GLcontext *ctx,
struct pipe_surface *srcSurf = srcRb->surface;
struct pipe_surface *dstSurf = dstRb->surface;
- srcY0 = srcRb->Base.Height - srcY0;
- srcY1 = srcRb->Base.Height - srcY1;
-
- dstY0 = dstRb->Base.Height - dstY0;
- dstY1 = dstRb->Base.Height - dstY1;
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ /* invert Y */
+ srcY0 = srcRb->Base.Height - srcY0;
+ srcY1 = srcRb->Base.Height - srcY1;
+
+ dstY0 = dstRb->Base.Height - dstY0;
+ dstY1 = dstRb->Base.Height - dstY1;
+ }
util_blit_pixels(st->blit,
srcSurf, srcX0, srcY0, srcX1, srcY1,
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
index c23938dc681..5ca15df602a 100644
--- a/src/mesa/state_tracker/st_cb_clear.c
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -49,14 +49,37 @@
#include "pipe/p_defines.h"
#include "pipe/p_winsys.h"
#include "util/u_pack_color.h"
+#include "util/u_simple_shaders.h"
+#include "util/u_draw_quad.h"
#include "cso_cache/cso_context.h"
/* XXX for testing draw module vertex passthrough: */
+/* XXX this hack is broken now */
#define TEST_DRAW_PASSTHROUGH 0
+void
+st_destroy_clear(struct st_context *st)
+{
+ struct pipe_context *pipe = st->pipe;
+
+ if (st->clear.fs) {
+ pipe->delete_fs_state(pipe, st->clear.fs);
+ st->clear.fs = NULL;
+ }
+ if (st->clear.vs) {
+ pipe->delete_vs_state(pipe, st->clear.vs);
+ st->clear.vs = NULL;
+ }
+ if (st->clear.vbuf) {
+ pipe->winsys->buffer_destroy(pipe->winsys, st->clear.vbuf);
+ st->clear.vbuf = NULL;
+ }
+}
+
+
static GLboolean
is_depth_stencil_format(enum pipe_format pipeFormat)
{
@@ -72,104 +95,6 @@ is_depth_stencil_format(enum pipe_format pipeFormat)
/**
- * Create a simple fragment shader that just passes through the fragment color.
- */
-static struct st_fragment_program *
-make_frag_shader(struct st_context *st)
-{
- GLcontext *ctx = st->ctx;
- struct st_fragment_program *stfp;
- struct gl_program *p;
- GLuint interpMode[16];
- GLuint i;
-
- /* XXX temporary */
- for (i = 0; i < 16; i++)
- interpMode[i] = TGSI_INTERPOLATE_LINEAR;
-
- p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
- if (!p)
- return NULL;
-
- p->NumInstructions = 2;
- p->Instructions = _mesa_alloc_instructions(2);
- if (!p->Instructions) {
- ctx->Driver.DeleteProgram(ctx, p);
- return NULL;
- }
- _mesa_init_instructions(p->Instructions, 2);
- /* MOV result.color, fragment.color; */
- p->Instructions[0].Opcode = OPCODE_MOV;
- p->Instructions[0].DstReg.File = PROGRAM_OUTPUT;
- p->Instructions[0].DstReg.Index = FRAG_RESULT_COLR;
- p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT;
- p->Instructions[0].SrcReg[0].Index = FRAG_ATTRIB_COL0;
- /* END; */
- p->Instructions[1].Opcode = OPCODE_END;
-
- p->InputsRead = FRAG_BIT_COL0;
- p->OutputsWritten = (1 << FRAG_RESULT_COLR);
-
- stfp = (struct st_fragment_program *) p;
- st_translate_fragment_program(st, stfp, NULL);
-
- return stfp;
-}
-
-
-/**
- * Create a simple vertex shader that just passes through the
- * vertex position and color.
- */
-static struct st_vertex_program *
-make_vertex_shader(struct st_context *st)
-{
- GLcontext *ctx = st->ctx;
- struct st_vertex_program *stvp;
- struct gl_program *p;
-
- p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
- if (!p)
- return NULL;
-
- p->NumInstructions = 3;
- p->Instructions = _mesa_alloc_instructions(3);
- if (!p->Instructions) {
- ctx->Driver.DeleteProgram(ctx, p);
- return NULL;
- }
- _mesa_init_instructions(p->Instructions, 3);
- /* MOV result.pos, vertex.pos; */
- p->Instructions[0].Opcode = OPCODE_MOV;
- p->Instructions[0].DstReg.File = PROGRAM_OUTPUT;
- p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS;
- p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT;
- p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS;
- /* MOV result.color, vertex.color; */
- p->Instructions[1].Opcode = OPCODE_MOV;
- p->Instructions[1].DstReg.File = PROGRAM_OUTPUT;
- p->Instructions[1].DstReg.Index = VERT_RESULT_COL0;
- p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT;
- p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_COLOR0;
- /* END; */
- p->Instructions[2].Opcode = OPCODE_END;
-
- p->InputsRead = VERT_BIT_POS | VERT_BIT_COLOR0;
- p->OutputsWritten = ((1 << VERT_RESULT_COL0) |
- (1 << VERT_RESULT_HPOS));
-
- stvp = (struct st_vertex_program *) p;
- st_translate_vertex_program(st, stvp, NULL);
-#if 0
- assert(stvp->cso);
-#endif
-
- return stvp;
-}
-
-
-
-/**
* Draw a screen-aligned quadrilateral.
* Coords are window coords with y=0=bottom. These coords will be transformed
* by the vertex shader and viewport transform (which will flip Y if needed).
@@ -179,45 +104,51 @@ draw_quad(GLcontext *ctx,
float x0, float y0, float x1, float y1, GLfloat z,
const GLfloat color[4])
{
- GLfloat verts[4][2][4]; /* four verts, two attribs, XYZW */
+ struct st_context *st = ctx->st;
+ struct pipe_context *pipe = st->pipe;
GLuint i;
+ void *buf;
-#if TEST_DRAW_PASSTHROUGH
- /* invert Y coords (may be off by one pixel) */
- y0 = ctx->DrawBuffer->Height - y0;
- y1 = ctx->DrawBuffer->Height - y1;
-#endif
+ if (!st->clear.vbuf) {
+ st->clear.vbuf = pipe->winsys->buffer_create(pipe->winsys, 32,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(st->clear.vertices));
+ }
/* positions */
- verts[0][0][0] = x0;
- verts[0][0][1] = y0;
+ st->clear.vertices[0][0][0] = x0;
+ st->clear.vertices[0][0][1] = y0;
- verts[1][0][0] = x1;
- verts[1][0][1] = y0;
+ st->clear.vertices[1][0][0] = x1;
+ st->clear.vertices[1][0][1] = y0;
- verts[2][0][0] = x1;
- verts[2][0][1] = y1;
+ st->clear.vertices[2][0][0] = x1;
+ st->clear.vertices[2][0][1] = y1;
- verts[3][0][0] = x0;
- verts[3][0][1] = y1;
+ st->clear.vertices[3][0][0] = x0;
+ st->clear.vertices[3][0][1] = y1;
/* same for all verts: */
for (i = 0; i < 4; i++) {
- verts[i][0][2] = z;
- verts[i][0][3] = 1.0;
- verts[i][1][0] = color[0];
- verts[i][1][1] = color[1];
- verts[i][1][2] = color[2];
- verts[i][1][3] = color[3];
+ st->clear.vertices[i][0][2] = z;
+ st->clear.vertices[i][0][3] = 1.0;
+ st->clear.vertices[i][1][0] = color[0];
+ st->clear.vertices[i][1][1] = color[1];
+ st->clear.vertices[i][1][2] = color[2];
+ st->clear.vertices[i][1][3] = color[3];
}
- st_draw_vertices(ctx, PIPE_PRIM_POLYGON, 4, (float *) verts, 2,
-#if TEST_DRAW_PASSTHROUGH
- GL_TRUE
-#else
- GL_FALSE
-#endif
- );
+ /* put vertex data into vbuf */
+ buf = pipe->winsys->buffer_map(pipe->winsys, st->clear.vbuf,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ memcpy(buf, st->clear.vertices, sizeof(st->clear.vertices));
+ pipe->winsys->buffer_unmap(pipe->winsys, st->clear.vbuf);
+
+ /* draw */
+ util_draw_vertex_buffer(pipe, st->clear.vbuf,
+ PIPE_PRIM_TRIANGLE_FAN,
+ 4, /* verts */
+ 2); /* attribs/vert */
}
@@ -234,9 +165,17 @@ clear_with_quad(GLcontext *ctx,
struct st_context *st = ctx->st;
struct pipe_context *pipe = st->pipe;
const GLfloat x0 = ctx->DrawBuffer->_Xmin;
- const GLfloat y0 = ctx->DrawBuffer->_Ymin;
const GLfloat x1 = ctx->DrawBuffer->_Xmax;
- const GLfloat y1 = ctx->DrawBuffer->_Ymax;
+ GLfloat y0, y1;
+
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ y0 = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax;
+ y1 = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin;
+ }
+ else {
+ y0 = ctx->DrawBuffer->_Ymin;
+ y1 = ctx->DrawBuffer->_Ymax;
+ }
/*
printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__,
@@ -299,35 +238,35 @@ clear_with_quad(GLcontext *ctx,
cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil);
}
- /* rasterizer state: nothing */
+ /* rasterizer state: bypass clipping */
{
struct pipe_rasterizer_state raster;
memset(&raster, 0, sizeof(raster));
-#if TEST_DRAW_PASSTHROUGH
raster.bypass_clipping = 1;
+#if TEST_DRAW_PASSTHROUGH
raster.bypass_vs = 1;
#endif
cso_set_rasterizer(st->cso_context, &raster);
}
/* fragment shader state: color pass-through program */
- {
- static struct st_fragment_program *stfp = NULL;
- if (!stfp) {
- stfp = make_frag_shader(st);
- }
- pipe->bind_fs_state(pipe, stfp->driver_shader);
+ if (!st->clear.fs) {
+ st->clear.fs = util_make_fragment_passthrough_shader(pipe);
}
+ pipe->bind_fs_state(pipe, st->clear.fs);
+
#if !TEST_DRAW_PASSTHROUGH
/* vertex shader state: color/position pass-through */
- {
- static struct st_vertex_program *stvp = NULL;
- if (!stvp) {
- stvp = make_vertex_shader(st);
- }
- pipe->bind_vs_state(pipe, stvp->driver_shader);
+ if (!st->clear.vs) {
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_COLOR };
+ const uint semantic_indexes[] = { 0, 0 };
+ st->clear.vs = util_make_vertex_passthrough_shader(pipe, 2,
+ semantic_names,
+ semantic_indexes);
}
+ pipe->bind_vs_state(pipe, st->clear.vs);
#endif
#if !TEST_DRAW_PASSTHROUGH
diff --git a/src/mesa/state_tracker/st_cb_clear.h b/src/mesa/state_tracker/st_cb_clear.h
index c715e56bd56..dfa4033faa6 100644
--- a/src/mesa/state_tracker/st_cb_clear.h
+++ b/src/mesa/state_tracker/st_cb_clear.h
@@ -31,6 +31,10 @@
extern void
+st_destroy_clear(struct st_context *st);
+
+
+extern void
st_init_clear_functions(struct dd_function_table *functions);
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 99d5e3e848f..b4cd93cd548 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -56,6 +56,7 @@
#include "pipe/p_inlines.h"
#include "pipe/p_winsys.h"
#include "util/p_tile.h"
+#include "util/u_draw_quad.h"
#include "shader/prog_instruction.h"
#include "cso_cache/cso_context.h"
@@ -85,140 +86,6 @@ is_passthrough_program(const struct gl_fragment_program *prog)
}
-/**
- * Make fragment program for glBitmap:
- * Sample the texture and kill the fragment if the bit is 0.
- * This program will be combined with the user's fragment program.
- */
-static struct st_fragment_program *
-make_bitmap_fragment_program(GLcontext *ctx)
-{
- struct st_fragment_program *stfp;
- struct gl_program *p;
- GLuint ic = 0;
-
- p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
- if (!p)
- return NULL;
-
- p->NumInstructions = 5;
-
- p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
- if (!p->Instructions) {
- ctx->Driver.DeleteProgram(ctx, p);
- return NULL;
- }
- _mesa_init_instructions(p->Instructions, p->NumInstructions);
-
- /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
- p->Instructions[ic].Opcode = OPCODE_TEX;
- p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
- p->Instructions[ic].DstReg.Index = 0;
- p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
- p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
- p->Instructions[ic].TexSrcUnit = 0;
- p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
- ic++;
-
- /* SWZ tmp0.x, tmp0.x, 1111; # tmp0.x = 1.0 */
- p->Instructions[ic].Opcode = OPCODE_SWZ;
- p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
- p->Instructions[ic].DstReg.Index = 0;
- p->Instructions[ic].DstReg.WriteMask = WRITEMASK_X;
- p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
- p->Instructions[ic].SrcReg[0].Index = 0;
- p->Instructions[ic].SrcReg[0].Swizzle
- = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE );
- ic++;
-
- /* SUB tmp0, tmp0.wwww, tmp0.xxxx; # tmp0.w -= 1 */
- p->Instructions[ic].Opcode = OPCODE_SUB;
- p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
- p->Instructions[ic].DstReg.Index = 0;
- p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
- p->Instructions[ic].SrcReg[0].Index = 0;
- p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_WWWW;
- p->Instructions[ic].SrcReg[1].File = PROGRAM_TEMPORARY;
- p->Instructions[ic].SrcReg[1].Index = 0;
- p->Instructions[ic].SrcReg[1].Swizzle = SWIZZLE_XXXX; /* 1.0 */
- ic++;
-
- /* KIL if tmp0 < 0 */
- p->Instructions[ic].Opcode = OPCODE_KIL;
- p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
- p->Instructions[ic].SrcReg[0].Index = 0;
- ic++;
-
- /* END; */
- p->Instructions[ic++].Opcode = OPCODE_END;
-
- assert(ic == p->NumInstructions);
-
- p->InputsRead = FRAG_BIT_TEX0;
- p->OutputsWritten = 0x0;
-
- stfp = (struct st_fragment_program *) p;
- stfp->Base.UsesKill = GL_TRUE;
- st_translate_fragment_program(ctx->st, stfp, NULL);
-
- return stfp;
-}
-
-
-/**
- * Combine basic bitmap fragment program with the user-defined program.
- */
-static struct st_fragment_program *
-combined_bitmap_fragment_program(GLcontext *ctx)
-{
- struct st_context *st = ctx->st;
- struct st_fragment_program *stfp;
-
- if (!st->bitmap.program) {
- /* create the basic bitmap fragment program */
- st->bitmap.program = make_bitmap_fragment_program(ctx);
- }
-
- if (st->bitmap.user_prog_sn == st->fp->serialNo) {
- /* re-use */
- stfp = st->bitmap.combined_prog;
- }
- else {
- /* Concatenate the bitmap program with the current user-defined program.
- */
- stfp = (struct st_fragment_program *)
- _mesa_combine_programs(ctx,
- &st->bitmap.program->Base.Base,
- &st->fp->Base.Base);
-
-#if 0
- {
- struct gl_program *p = &stfp->Base.Base;
- printf("Combined bitmap program:\n");
- _mesa_print_program(p);
- printf("InputsRead: 0x%x\n", p->InputsRead);
- printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
- _mesa_print_parameter_list(p->Parameters);
- }
-#endif
-
- /* translate to TGSI tokens */
- st_translate_fragment_program(st, stfp, NULL);
-
- /* save new program, update serial numbers */
- st->bitmap.user_prog_sn = st->fp->serialNo;
- st->bitmap.combined_prog = stfp;
- }
-
- /* Ideally we'd have updated the pipe constants during the normal
- * st/atom mechanism. But we can't since this is specific to glBitmap.
- */
- st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
-
- return stfp;
-}
-
-
/**
* Make fragment shader for glDraw/CopyPixels. This shader is made
@@ -351,7 +218,7 @@ make_fragment_shader_z(struct st_context *st)
* Create a simple vertex shader that just passes through the
* vertex position and texcoord (and optionally, color).
*/
-struct st_vertex_program *
+static struct st_vertex_program *
st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor)
{
/* only make programs once and re-use */
@@ -655,14 +522,14 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
cso_save_rasterizer(cso);
cso_save_viewport(cso);
- /* setup state: just scissor */
+ /* rasterizer state: just scissor */
{
- struct pipe_rasterizer_state setup;
- memset(&setup, 0, sizeof(setup));
+ struct pipe_rasterizer_state rasterizer;
+ memset(&rasterizer, 0, sizeof(rasterizer));
if (ctx->Scissor.Enabled)
- setup.scissor = 1;
+ rasterizer.scissor = 1;
- cso_set_rasterizer(cso, &setup);
+ cso_set_rasterizer(cso, &rasterizer);
}
/* fragment shader state: TEX lookup program */
@@ -990,153 +857,6 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
-/**
- * Create a texture which represents a bitmap image.
- */
-static struct pipe_texture *
-make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack,
- const GLubyte *bitmap)
-{
- struct pipe_context *pipe = ctx->st->pipe;
- struct pipe_screen *screen = pipe->screen;
- struct pipe_surface *surface;
- uint format = 0, cpp, comp;
- ubyte *dest;
- struct pipe_texture *pt;
- int row, col;
-
- /* find a texture format we know */
- if (screen->is_format_supported( screen, PIPE_FORMAT_U_I8, PIPE_TEXTURE )) {
- format = PIPE_FORMAT_U_I8;
- cpp = 1;
- comp = 0;
- }
- else if (screen->is_format_supported( screen, PIPE_FORMAT_A8R8G8B8_UNORM, PIPE_TEXTURE )) {
- format = PIPE_FORMAT_A8R8G8B8_UNORM;
- cpp = 4;
- comp = 3; /* alpha channel */ /*XXX little-endian dependency */
- }
- else {
- /* XXX support more formats */
- assert( 0 );
- }
-
- /**
- * Create a texture.
- */
- pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, width, height,
- 1, 0);
- if (!pt)
- return NULL;
-
- if (unpack->BufferObj && unpack->BufferObj->Name) {
- /*
- pt->region = buffer_object_region(unpack->BufferObj);
- */
- printf("st_Bitmap (sourcing from PBO not implemented yet)\n");
- }
-
- surface = screen->get_tex_surface(screen, pt, 0, 0, 0);
-
- /* map texture surface */
- dest = pipe_surface_map(surface);
-
- /* Put image into texture surface.
- * Note that the image is actually going to be upside down in
- * the texture. We deal with that with texcoords.
- */
-
- for (row = 0; row < height; row++) {
- const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
- bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
- ubyte *destRow = dest + row * surface->pitch * cpp;
-
- if (unpack->LsbFirst) {
- /* Lsb first */
- GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
- for (col = 0; col < width; col++) {
-
- /* set texel to 255 if bit is set */
- destRow[comp] = (*src & mask) ? 255 : 0;
- destRow += cpp;
-
- if (mask == 128U) {
- src++;
- mask = 1U;
- }
- else {
- mask = mask << 1;
- }
- }
-
- /* get ready for next row */
- if (mask != 1)
- src++;
- }
- else {
- /* Msb first */
- GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
- for (col = 0; col < width; col++) {
-
- /* set texel to 255 if bit is set */
- destRow[comp] =(*src & mask) ? 255 : 0;
- destRow += cpp;
-
- if (mask == 1U) {
- src++;
- mask = 128U;
- }
- else {
- mask = mask >> 1;
- }
- }
-
- /* get ready for next row */
- if (mask != 128)
- src++;
- }
-
- } /* row */
-
- /* Release surface */
- pipe_surface_unmap(surface);
- pipe_surface_reference(&surface, NULL);
- pipe->texture_update(pipe, pt, 0, 0x1);
-
- pt->format = format;
-
- return pt;
-}
-
-
-
-static void
-st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
- const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
-{
- struct st_fragment_program *stfp;
- struct st_vertex_program *stvp;
- struct st_context *st = ctx->st;
- struct pipe_texture *pt;
-
- stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
- stfp = combined_bitmap_fragment_program(ctx);
-
- st_validate_state(st);
-
- pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
- if (pt) {
- draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
- width, height, 1.0, 1.0,
- pt, stvp, stfp,
- ctx->Current.RasterColor, GL_FALSE);
-
- pipe_texture_reference(&pt, NULL);
- }
-}
-
-
static void
copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
@@ -1337,5 +1057,4 @@ void st_init_drawpixels_functions(struct dd_function_table *functions)
{
functions->DrawPixels = st_DrawPixels;
functions->CopyPixels = st_CopyPixels;
- functions->Bitmap = st_Bitmap;
}
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.h b/src/mesa/state_tracker/st_cb_drawpixels.h
index b8b906f06bc..71ba4870200 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.h
+++ b/src/mesa/state_tracker/st_cb_drawpixels.h
@@ -30,10 +30,6 @@
#define ST_CB_DRAWPIXELS_H
-extern struct st_vertex_program *
-st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor);
-
-
extern void st_init_drawpixels_functions(struct dd_function_table *functions);
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 306b27c4235..a6c1a353552 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -564,7 +564,8 @@ st_TexImage(GLcontext * ctx,
if (!stObj->pt) {
guess_and_alloc_texture(ctx->st, stObj, stImage);
if (!stObj->pt) {
- DBG("guess_and_alloc_texture: failed\n");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+ return;
}
}
@@ -1379,7 +1380,7 @@ copy_image_data_to_texture(struct st_context *st,
/**
* Called during state validation. When this function is finished,
* the texture object should be ready for rendering.
- * \return GL_FALSE if a texture border is present, GL_TRUE otherwise
+ * \return GL_TRUE for success, GL_FALSE for failure (out of mem)
*/
GLboolean
st_finalize_texture(GLcontext *ctx,
@@ -1405,6 +1406,7 @@ st_finalize_texture(GLcontext *ctx,
calculate_first_last_level(stObj);
firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
+#if 0
/* Fallback case:
*/
if (firstImage->base.Border) {
@@ -1413,7 +1415,7 @@ st_finalize_texture(GLcontext *ctx,
}
return GL_FALSE;
}
-
+#endif
/* If both firstImage and stObj point to a texture which can contain
* all active images, favour firstImage. Note that because of the
@@ -1466,6 +1468,10 @@ st_finalize_texture(GLcontext *ctx,
firstImage->base.Height,
firstImage->base.Depth,
comp_byte);
+ if (!stObj->pt) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+ return GL_FALSE;
+ }
}
/* Pull in any images not in the object's texture:
@@ -1486,7 +1492,6 @@ st_finalize_texture(GLcontext *ctx,
}
}
-
return GL_TRUE;
}
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index e1fc885e0e7..d9e87229764 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -35,8 +35,9 @@
#include "st_public.h"
#include "st_context.h"
#include "st_cb_accum.h"
-#include "st_cb_bufferobjects.h"
+#include "st_cb_bitmap.h"
#include "st_cb_blit.h"
+#include "st_cb_bufferobjects.h"
#include "st_cb_clear.h"
#include "st_cb_drawpixels.h"
#include "st_cb_fbo.h"
@@ -154,7 +155,9 @@ static void st_destroy_context_priv( struct st_context *st )
st_destroy_atoms( st );
st_destroy_draw( st );
st_destroy_generate_mipmap(st);
+ st_destroy_bitmap(st);
st_destroy_blit(st);
+ st_destroy_clear(st);
_vbo_DestroyContext(st->ctx);
@@ -220,8 +223,9 @@ void st_init_driver_functions(struct dd_function_table *functions)
_mesa_init_glsl_driver_functions(functions);
st_init_accum_functions(functions);
- st_init_bufferobject_functions(functions);
+ st_init_bitmap_functions(functions);
st_init_blit_functions(functions);
+ st_init_bufferobject_functions(functions);
st_init_clear_functions(functions);
st_init_drawpixels_functions(functions);
st_init_fbo_functions(functions);
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index ca8307c4ba0..2d37086799d 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -142,12 +142,24 @@ struct st_context
GLuint combined_prog_sn;
} pixel_xfer;
+ /** for glBitmap */
struct {
struct st_fragment_program *program; /**< bitmap tex/kil program */
GLuint user_prog_sn; /**< user fragment program serial no. */
struct st_fragment_program *combined_prog;
+ void *vs;
+ float vertices[4][3][4]; /**< vertex pos + color + texcoord */
+ struct pipe_buffer *vbuf;
} bitmap;
+ /** for glClear */
+ struct {
+ void *vs;
+ void *fs;
+ float vertices[4][2][4]; /**< vertex pos + color */
+ struct pipe_buffer *vbuf;
+ } clear;
+
struct gen_mipmap_state *gen_mipmap;
struct blit_state *blit;
diff --git a/src/mesa/state_tracker/st_debug.c b/src/mesa/state_tracker/st_debug.c
index 8b9b91aa348..23ecfff0aa4 100644
--- a/src/mesa/state_tracker/st_debug.c
+++ b/src/mesa/state_tracker/st_debug.c
@@ -50,9 +50,10 @@ st_print_current(void)
{
GET_CURRENT_CONTEXT(ctx);
struct st_context *st = ctx->st;
- int i;
#if 0
+ int i;
+
printf("Vertex Transform Inputs:\n");
for (i = 0; i < st->vp->state.num_inputs; i++) {
printf(" Slot %d: VERT_ATTRIB_%d\n", i, st->vp->index_to_input[i]);