summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2011-07-21 10:38:21 -0600
committerBrian Paul <[email protected]>2011-07-21 10:38:21 -0600
commit636d01bd61cac83e13c3c64874e7e34e828ca93a (patch)
treec11ff84ae5647a60bf7d74c7bdb4061756644ca7
parentecc6a26a3d602e8b649c441077e005dfeb77aff2 (diff)
parent57aa597b3d5dac0fc59c05557dafec59e14e1019 (diff)
Merge branch 'gallium-polygon-stipple'
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_scan.c38
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_scan.h3
-rw-r--r--src/gallium/auxiliary/util/u_pstipple.c43
-rw-r--r--src/gallium/drivers/softpipe/sp_clear.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_context.c14
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h15
-rw-r--r--src/gallium/drivers/softpipe/sp_draw_arrays.c4
-rw-r--r--src/gallium/drivers/softpipe/sp_fs.h16
-rw-r--r--src/gallium/drivers/softpipe/sp_fs_exec.c40
-rw-r--r--src/gallium/drivers/softpipe/sp_fs_sse.c25
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_blend.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_depth_test.c10
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_fs.c10
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_pipe.c22
-rw-r--r--src/gallium/drivers/softpipe/sp_setup.c39
-rw-r--r--src/gallium/drivers/softpipe/sp_state.h65
-rw-r--r--src/gallium/drivers/softpipe/sp_state_derived.c126
-rw-r--r--src/gallium/drivers/softpipe/sp_state_sampler.c3
-rw-r--r--src/gallium/drivers/softpipe/sp_state_shader.c138
19 files changed, 447 insertions, 168 deletions
diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c
index 83c6ac75e54..f165f8240e6 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_scan.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c
@@ -200,19 +200,20 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
info->file_max[file] = MAX2(info->file_max[file], (int)reg);
}
break;
+
case TGSI_TOKEN_TYPE_PROPERTY:
- {
- const struct tgsi_full_property *fullprop
- = &parse.FullToken.FullProperty;
+ {
+ const struct tgsi_full_property *fullprop
+ = &parse.FullToken.FullProperty;
- info->properties[info->num_properties].name =
- fullprop->Property.PropertyName;
- memcpy(info->properties[info->num_properties].data,
- fullprop->u, 8 * sizeof(unsigned));;
+ info->properties[info->num_properties].name =
+ fullprop->Property.PropertyName;
+ memcpy(info->properties[info->num_properties].data,
+ fullprop->u, 8 * sizeof(unsigned));;
- ++info->num_properties;
- }
- break;
+ ++info->num_properties;
+ }
+ break;
default:
assert( 0 );
@@ -222,6 +223,23 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
info->uses_kill = (info->opcode_count[TGSI_OPCODE_KIL] ||
info->opcode_count[TGSI_OPCODE_KILP]);
+ /* extract simple properties */
+ for (i = 0; i < info->num_properties; ++i) {
+ switch (info->properties[i].name) {
+ case TGSI_PROPERTY_FS_COORD_ORIGIN:
+ info->origin_lower_left = info->properties[i].data[0];
+ break;
+ case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
+ info->pixel_center_integer = info->properties[i].data[0];
+ break;
+ case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
+ info->color0_writes_all_cbufs = info->properties[i].data[0];
+ break;
+ default:
+ ;
+ }
+ }
+
tgsi_parse_free (&parse);
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.h b/src/gallium/auxiliary/tgsi/tgsi_scan.h
index 53ab3d509dd..d6e593b3968 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_scan.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_scan.h
@@ -68,6 +68,9 @@ struct tgsi_shader_info
boolean writes_edgeflag; /**< vertex shader outputs edgeflag */
boolean uses_kill; /**< KIL or KILP instruction used? */
boolean uses_instanceid;
+ boolean origin_lower_left;
+ boolean pixel_center_integer;
+ boolean color0_writes_all_cbufs;
/**
* Bitmask indicating which register files are accessed with
diff --git a/src/gallium/auxiliary/util/u_pstipple.c b/src/gallium/auxiliary/util/u_pstipple.c
index f79a6938d1d..ac0df8c1a9c 100644
--- a/src/gallium/auxiliary/util/u_pstipple.c
+++ b/src/gallium/auxiliary/util/u_pstipple.c
@@ -52,6 +52,7 @@
#include "tgsi/tgsi_transform.h"
#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_scan.h"
/** Approx number of new tokens for instructions in pstip_transform_inst() */
#define NUM_NEW_TOKENS 50
@@ -175,6 +176,7 @@ util_pstipple_create_sampler(struct pipe_context *pipe)
*/
struct pstip_transform_context {
struct tgsi_transform_context base;
+ struct tgsi_shader_info info;
uint tempsUsed; /**< bitmask */
int wincoordInput;
int maxInput;
@@ -183,12 +185,13 @@ struct pstip_transform_context {
int texTemp; /**< temp registers */
int numImmed;
boolean firstInstruction;
+ uint coordOrigin;
};
/**
* TGSI declaration transform callback.
- * Look for a free sampler, a free input attrib, and two free temp regs.
+ * Track samplers used, temps used, inputs used.
*/
static void
pstip_transform_decl(struct tgsi_transform_context *ctx,
@@ -197,10 +200,11 @@ pstip_transform_decl(struct tgsi_transform_context *ctx,
struct pstip_transform_context *pctx =
(struct pstip_transform_context *) ctx;
+ /* XXX we can use tgsi_shader_info instead of some of this */
+
if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
uint i;
- for (i = decl->Range.First;
- i <= decl->Range.Last; i++) {
+ for (i = decl->Range.First; i <= decl->Range.Last; i++) {
pctx->samplersUsed |= 1 << i;
}
}
@@ -211,8 +215,7 @@ pstip_transform_decl(struct tgsi_transform_context *ctx,
}
else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
uint i;
- for (i = decl->Range.First;
- i <= decl->Range.Last; i++) {
+ for (i = decl->Range.First; i <= decl->Range.Last; i++) {
pctx->tempsUsed |= (1 << i);
}
}
@@ -243,8 +246,16 @@ free_bit(uint bitfield)
/**
* TGSI instruction transform callback.
- * Replace writes to result.color w/ a temp reg.
- * Upon END instruction, insert texture sampling code for antialiasing.
+ * Before the first instruction, insert our new code to sample the
+ * stipple texture (using the fragment coord register) then kill the
+ * fragment if the stipple texture bit is off.
+ *
+ * Insert:
+ * declare new registers
+ * MUL texTemp, INPUT[wincoord], 1/32;
+ * TEX texTemp, texTemp, sampler;
+ * KIL -texTemp; # if -texTemp < 0, KILL fragment
+ * [...original code...]
*/
static void
pstip_transform_inst(struct tgsi_transform_context *ctx,
@@ -261,7 +272,7 @@ pstip_transform_inst(struct tgsi_transform_context *ctx,
uint i;
int wincoordInput;
- /* find free sampler */
+ /* find free texture sampler */
pctx->freeSampler = free_bit(pctx->samplersUsed);
if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
@@ -271,7 +282,7 @@ pstip_transform_inst(struct tgsi_transform_context *ctx,
else
wincoordInput = pctx->wincoordInput;
- /* find one free temp reg */
+ /* find one free temp register */
for (i = 0; i < 32; i++) {
if ((pctx->tempsUsed & (1 << i)) == 0) {
/* found a free temp */
@@ -397,6 +408,7 @@ util_pstipple_create_fragment_shader(struct pipe_context *pipe,
struct pipe_shader_state *new_fs;
struct pstip_transform_context transform;
const uint newLen = tgsi_num_tokens(fs->tokens) + NUM_NEW_TOKENS;
+ unsigned i;
new_fs = MALLOC(sizeof(*new_fs));
if (!new_fs)
@@ -408,22 +420,33 @@ util_pstipple_create_fragment_shader(struct pipe_context *pipe,
return NULL;
}
+ /* Setup shader transformation info/context.
+ */
memset(&transform, 0, sizeof(transform));
transform.wincoordInput = -1;
transform.maxInput = -1;
transform.texTemp = -1;
transform.firstInstruction = TRUE;
+ transform.coordOrigin = TGSI_FS_COORD_ORIGIN_UPPER_LEFT;
transform.base.transform_instruction = pstip_transform_inst;
transform.base.transform_declaration = pstip_transform_decl;
transform.base.transform_immediate = pstip_transform_immed;
+ tgsi_scan_shader(fs->tokens, &transform.info);
+
+ /* find fragment coordinate origin property */
+ for (i = 0; i < transform.info.num_properties; i++) {
+ if (transform.info.properties[i].name == TGSI_PROPERTY_FS_COORD_ORIGIN)
+ transform.coordOrigin = transform.info.properties[i].data[0];
+ }
+
tgsi_transform_shader(fs->tokens,
(struct tgsi_token *) new_fs->tokens,
newLen, &transform.base);
#if 0 /* DEBUG */
tgsi_dump(fs->tokens, 0);
- tgsi_dump(pstip_fs.tokens, 0);
+ tgsi_dump(new_fs->tokens, 0);
#endif
assert(transform.freeSampler < PIPE_MAX_SAMPLERS);
diff --git a/src/gallium/drivers/softpipe/sp_clear.c b/src/gallium/drivers/softpipe/sp_clear.c
index ae3f00f3387..22e8a2e5817 100644
--- a/src/gallium/drivers/softpipe/sp_clear.c
+++ b/src/gallium/drivers/softpipe/sp_clear.c
@@ -60,7 +60,7 @@ softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
return;
#if 0
- softpipe_update_derived(softpipe); /* not needed?? */
+ softpipe_update_derived(softpipe, PIPE_PRIM_TRIANGLES); /* not needed?? */
#endif
if (buffers & PIPE_CLEAR_COLOR) {
diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
index 2c43602ea1c..c97b0333035 100644
--- a/src/gallium/drivers/softpipe/sp_context.c
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -35,6 +35,7 @@
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
+#include "util/u_pstipple.h"
#include "util/u_inlines.h"
#include "tgsi/tgsi_exec.h"
#include "vl/vl_decoder.h"
@@ -90,6 +91,14 @@ softpipe_destroy( struct pipe_context *pipe )
struct softpipe_context *softpipe = softpipe_context( pipe );
uint i;
+#if DO_PSTIPPLE_IN_HELPER_MODULE
+ if (softpipe->pstipple.sampler)
+ pipe->delete_sampler_state(pipe, softpipe->pstipple.sampler);
+
+ pipe_resource_reference(&softpipe->pstipple.texture, NULL);
+ pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, NULL);
+#endif
+
if (softpipe->draw)
draw_destroy( softpipe->draw );
@@ -346,6 +355,11 @@ softpipe_create_context( struct pipe_screen *screen,
sp_init_surface_functions(softpipe);
+#if DO_PSTIPPLE_IN_HELPER_MODULE
+ /* create the polgon stipple sampler */
+ softpipe->pstipple.sampler = util_pstipple_create_sampler(&softpipe->pipe);
+#endif
+
return &softpipe->pipe;
fail:
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
index a572ee8cf00..410b0a65792 100644
--- a/src/gallium/drivers/softpipe/sp_context.h
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -38,8 +38,11 @@
#include "sp_quad_pipe.h"
-/** Do polygon stipple in the driver here, or in the draw module? */
-#define DO_PSTIPPLE_IN_DRAW_MODULE 1
+/** Do polygon stipple in the draw module? */
+#define DO_PSTIPPLE_IN_DRAW_MODULE 0
+
+/** Do polygon stipple with the util module? */
+#define DO_PSTIPPLE_IN_HELPER_MODULE 1
struct softpipe_vbuf_render;
@@ -64,6 +67,7 @@ struct softpipe_context {
struct pipe_depth_stencil_alpha_state *depth_stencil;
struct pipe_rasterizer_state *rasterizer;
struct sp_fragment_shader *fs;
+ struct sp_fragment_shader_variant *fs_variant;
struct sp_vertex_shader *vs;
struct sp_geometry_shader *gs;
struct sp_velems_state *velems;
@@ -143,6 +147,13 @@ struct softpipe_context {
struct pipe_query *render_cond_query;
uint render_cond_mode;
+ /** Polygon stipple items */
+ struct {
+ struct pipe_resource *texture;
+ struct pipe_sampler_state *sampler;
+ struct pipe_sampler_view *sampler_view;
+ } pstipple;
+
/** Software quad rendering pipeline */
struct {
struct quad_stage *shade;
diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
index 01b4ca985d0..69b5b96b4fd 100644
--- a/src/gallium/drivers/softpipe/sp_draw_arrays.c
+++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
@@ -64,7 +64,7 @@ softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode)
sp->reduced_api_prim = u_reduced_prim(mode);
if (sp->dirty) {
- softpipe_update_derived(sp);
+ softpipe_update_derived(sp, sp->reduced_api_prim);
}
softpipe_map_transfers(sp);
@@ -122,7 +122,7 @@ softpipe_draw_vbo(struct pipe_context *pipe,
sp->reduced_api_prim = u_reduced_prim(info->mode);
if (sp->dirty) {
- softpipe_update_derived(sp);
+ softpipe_update_derived(sp, sp->reduced_api_prim);
}
softpipe_map_transfers(sp);
diff --git a/src/gallium/drivers/softpipe/sp_fs.h b/src/gallium/drivers/softpipe/sp_fs.h
index 4792ace3a33..d46d7d5a657 100644
--- a/src/gallium/drivers/softpipe/sp_fs.h
+++ b/src/gallium/drivers/softpipe/sp_fs.h
@@ -31,17 +31,15 @@
#ifndef SP_FS_H
#define SP_FS_H
-struct sp_fragment_shader *
-softpipe_create_fs_exec(struct softpipe_context *softpipe,
- const struct pipe_shader_state *templ);
-struct sp_fragment_shader *
-softpipe_create_fs_sse(struct softpipe_context *softpipe,
- const struct pipe_shader_state *templ);
+struct sp_fragment_shader_variant *
+softpipe_create_fs_variant_exec(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ);
+
+struct sp_fragment_shader_variant *
+softpipe_create_fs_variant_sse(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ);
-struct sp_fragment_shader *
-softpipe_create_fs_llvm(struct softpipe_context *softpipe,
- const struct pipe_shader_state *templ);
struct tgsi_interp_coef;
struct tgsi_exec_vector;
diff --git a/src/gallium/drivers/softpipe/sp_fs_exec.c b/src/gallium/drivers/softpipe/sp_fs_exec.c
index 346e1b402ba..779b8c4995c 100644
--- a/src/gallium/drivers/softpipe/sp_fs_exec.c
+++ b/src/gallium/drivers/softpipe/sp_fs_exec.c
@@ -42,25 +42,25 @@
/**
- * Subclass of sp_fragment_shader
+ * Subclass of sp_fragment_shader_variant
*/
struct sp_exec_fragment_shader
{
- struct sp_fragment_shader base;
+ struct sp_fragment_shader_variant base;
/* No other members for now */
};
/** cast wrapper */
static INLINE struct sp_exec_fragment_shader *
-sp_exec_fragment_shader(const struct sp_fragment_shader *base)
+sp_exec_fragment_shader(const struct sp_fragment_shader_variant *var)
{
- return (struct sp_exec_fragment_shader *) base;
+ return (struct sp_exec_fragment_shader *) var;
}
static void
-exec_prepare( const struct sp_fragment_shader *base,
+exec_prepare( const struct sp_fragment_shader_variant *var,
struct tgsi_exec_machine *machine,
struct tgsi_sampler **samplers )
{
@@ -68,9 +68,9 @@ exec_prepare( const struct sp_fragment_shader *base,
* Bind tokens/shader to the interpreter's machine state.
* Avoid redundant binding.
*/
- if (machine->Tokens != base->shader.tokens) {
+ if (machine->Tokens != var->tokens) {
tgsi_exec_machine_bind_shader( machine,
- base->shader.tokens,
+ var->tokens,
PIPE_MAX_SAMPLERS,
samplers );
}
@@ -118,7 +118,7 @@ setup_pos_vector(const struct tgsi_interp_coef *coef,
* interface:
*/
static unsigned
-exec_run( const struct sp_fragment_shader *base,
+exec_run( const struct sp_fragment_shader_variant *var,
struct tgsi_exec_machine *machine,
struct quad_header *quad )
{
@@ -136,9 +136,9 @@ exec_run( const struct sp_fragment_shader *base,
/* store outputs */
{
- const ubyte *sem_name = base->info.output_semantic_name;
- const ubyte *sem_index = base->info.output_semantic_index;
- const uint n = base->info.num_outputs;
+ const ubyte *sem_name = var->info.output_semantic_name;
+ const ubyte *sem_index = var->info.output_semantic_index;
+ const uint n = var->info.num_outputs;
uint i;
for (i = 0; i < n; i++) {
switch (sem_name[i]) {
@@ -180,29 +180,23 @@ exec_run( const struct sp_fragment_shader *base,
static void
-exec_delete( struct sp_fragment_shader *base )
+exec_delete( struct sp_fragment_shader_variant *var )
{
- FREE((void *) base->shader.tokens);
- FREE(base);
+ FREE( (void *) var->tokens );
+ FREE(var);
}
-struct sp_fragment_shader *
-softpipe_create_fs_exec(struct softpipe_context *softpipe,
- const struct pipe_shader_state *templ)
+struct sp_fragment_shader_variant *
+softpipe_create_fs_variant_exec(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ)
{
struct sp_exec_fragment_shader *shader;
- /* Decide whether we'll be codegenerating this shader and if so do
- * that now.
- */
-
shader = CALLOC_STRUCT(sp_exec_fragment_shader);
if (!shader)
return NULL;
- /* we need to keep a local copy of the tokens */
- shader->base.shader.tokens = tgsi_dup_tokens(templ->tokens);
shader->base.prepare = exec_prepare;
shader->base.run = exec_run;
shader->base.delete = exec_delete;
diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c
index 5b18cd035e3..c873af125bd 100644
--- a/src/gallium/drivers/softpipe/sp_fs_sse.c
+++ b/src/gallium/drivers/softpipe/sp_fs_sse.c
@@ -48,11 +48,11 @@
/**
- * Subclass of sp_fragment_shader
+ * Subclass of sp_fragment_shader_variant
*/
struct sp_sse_fragment_shader
{
- struct sp_fragment_shader base;
+ struct sp_fragment_shader_variant base;
struct x86_function sse2_program;
tgsi_sse2_fs_function func;
float immediates[TGSI_EXEC_NUM_IMMEDIATES][4];
@@ -61,14 +61,14 @@ struct sp_sse_fragment_shader
/** cast wrapper */
static INLINE struct sp_sse_fragment_shader *
-sp_sse_fragment_shader(const struct sp_fragment_shader *base)
+sp_sse_fragment_shader(const struct sp_fragment_shader_variant *base)
{
return (struct sp_sse_fragment_shader *) base;
}
static void
-fs_sse_prepare( const struct sp_fragment_shader *base,
+fs_sse_prepare( const struct sp_fragment_shader_variant *base,
struct tgsi_exec_machine *machine,
struct tgsi_sampler **samplers )
{
@@ -119,7 +119,7 @@ setup_pos_vector(const struct tgsi_interp_coef *coef,
* TODO: process >1 quad at a time
*/
static unsigned
-fs_sse_run( const struct sp_fragment_shader *base,
+fs_sse_run( const struct sp_fragment_shader_variant *base,
struct tgsi_exec_machine *machine,
struct quad_header *quad )
{
@@ -189,7 +189,7 @@ fs_sse_run( const struct sp_fragment_shader *base,
static void
-fs_sse_delete( struct sp_fragment_shader *base )
+fs_sse_delete( struct sp_fragment_shader_variant *base )
{
struct sp_sse_fragment_shader *shader = sp_sse_fragment_shader(base);
@@ -198,9 +198,9 @@ fs_sse_delete( struct sp_fragment_shader *base )
}
-struct sp_fragment_shader *
-softpipe_create_fs_sse(struct softpipe_context *softpipe,
- const struct pipe_shader_state *templ)
+struct sp_fragment_shader_variant *
+softpipe_create_fs_variant_sse(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ)
{
struct sp_sse_fragment_shader *shader;
@@ -226,7 +226,6 @@ softpipe_create_fs_sse(struct softpipe_context *softpipe,
return NULL;
}
- shader->base.shader.tokens = NULL; /* don't hold reference to templ->tokens */
shader->base.prepare = fs_sse_prepare;
shader->base.run = fs_sse_run;
shader->base.delete = fs_sse_delete;
@@ -239,9 +238,9 @@ softpipe_create_fs_sse(struct softpipe_context *softpipe,
/* Maybe put this variant in the header file.
*/
-struct sp_fragment_shader *
-softpipe_create_fs_sse(struct softpipe_context *softpipe,
- const struct pipe_shader_state *templ)
+struct sp_fragment_shader_variant *
+softpipe_create_fs_variant_sse(struct softpipe_context *softpipe,
+ const struct pipe_shader_state *templ)
{
return NULL;
}
diff --git a/src/gallium/drivers/softpipe/sp_quad_blend.c b/src/gallium/drivers/softpipe/sp_quad_blend.c
index 76cfc0bf51c..04bfd14b7c6 100644
--- a/src/gallium/drivers/softpipe/sp_quad_blend.c
+++ b/src/gallium/drivers/softpipe/sp_quad_blend.c
@@ -797,7 +797,7 @@ blend_fallback(struct quad_stage *qs,
unsigned cbuf;
boolean write_all;
- write_all = softpipe->fs->color0_writes_all_cbufs;
+ write_all = softpipe->fs_variant->info.color0_writes_all_cbufs;
for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++)
{
diff --git a/src/gallium/drivers/softpipe/sp_quad_depth_test.c b/src/gallium/drivers/softpipe/sp_quad_depth_test.c
index 15f3a8fd813..a349f0d1f3c 100644
--- a/src/gallium/drivers/softpipe/sp_quad_depth_test.c
+++ b/src/gallium/drivers/softpipe/sp_quad_depth_test.c
@@ -727,9 +727,9 @@ depth_test_quads_fallback(struct quad_stage *qs,
unsigned nr)
{
unsigned i, pass = 0;
- const struct sp_fragment_shader *fs = qs->softpipe->fs;
- boolean interp_depth = !fs->info.writes_z;
- boolean shader_stencil_ref = fs->info.writes_stencil;
+ const struct tgsi_shader_info *fsInfo = &qs->softpipe->fs_variant->info;
+ boolean interp_depth = !fsInfo->writes_z;
+ boolean shader_stencil_ref = fsInfo->writes_stencil;
struct depth_data data;
data.use_shader_stencil_refs = FALSE;
@@ -838,7 +838,9 @@ choose_depth_test(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
- boolean interp_depth = !qs->softpipe->fs->info.writes_z;
+ const struct tgsi_shader_info *fsInfo = &qs->softpipe->fs_variant->info;
+
+ boolean interp_depth = !fsInfo->writes_z;
boolean alpha = qs->softpipe->depth_stencil->alpha.enabled;
diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c
index 90f4787d599..d74d6d4914e 100644
--- a/src/gallium/drivers/softpipe/sp_quad_fs.c
+++ b/src/gallium/drivers/softpipe/sp_quad_fs.c
@@ -74,7 +74,7 @@ shade_quad(struct quad_stage *qs, struct quad_header *quad)
struct tgsi_exec_machine *machine = softpipe->fs_machine;
/* run shader */
- return softpipe->fs->run( softpipe->fs, machine, quad );
+ return softpipe->fs_variant->run( softpipe->fs_variant, machine, quad );
}
@@ -140,10 +140,10 @@ shade_begin(struct quad_stage *qs)
{
struct softpipe_context *softpipe = qs->softpipe;
- softpipe->fs->prepare( softpipe->fs,
- softpipe->fs_machine,
- (struct tgsi_sampler **)
- softpipe->tgsi.frag_samplers_list );
+ softpipe->fs_variant->prepare( softpipe->fs_variant,
+ softpipe->fs_machine,
+ (struct tgsi_sampler **)
+ softpipe->tgsi.frag_samplers_list );
qs->next->begin(qs->next);
}
diff --git a/src/gallium/drivers/softpipe/sp_quad_pipe.c b/src/gallium/drivers/softpipe/sp_quad_pipe.c
index 2cfd02a22c6..0c4506ae8f4 100644
--- a/src/gallium/drivers/softpipe/sp_quad_pipe.c
+++ b/src/gallium/drivers/softpipe/sp_quad_pipe.c
@@ -30,9 +30,9 @@
#include "sp_state.h"
#include "pipe/p_shader_tokens.h"
+
static void
-sp_push_quad_first( struct softpipe_context *sp,
- struct quad_stage *quad )
+insert_stage_at_head(struct softpipe_context *sp, struct quad_stage *quad)
{
quad->next = sp->quad.first;
sp->quad.first = quad;
@@ -46,24 +46,24 @@ sp_build_quad_pipeline(struct softpipe_context *sp)
sp->depth_stencil->depth.enabled &&
sp->framebuffer.zsbuf &&
!sp->depth_stencil->alpha.enabled &&
- !sp->fs->info.uses_kill &&
- !sp->fs->info.writes_z &&
- !sp->fs->info.writes_stencil;
+ !sp->fs_variant->info.uses_kill &&
+ !sp->fs_variant->info.writes_z &&
+ !sp->fs_variant->info.writes_stencil;
sp->quad.first = sp->quad.blend;
if (early_depth_test) {
- sp_push_quad_first( sp, sp->quad.shade );
- sp_push_quad_first( sp, sp->quad.depth_test );
+ insert_stage_at_head( sp, sp->quad.shade );
+ insert_stage_at_head( sp, sp->quad.depth_test );
}
else {
- sp_push_quad_first( sp, sp->quad.depth_test );
- sp_push_quad_first( sp, sp->quad.shade );
+ insert_stage_at_head( sp, sp->quad.depth_test );
+ insert_stage_at_head( sp, sp->quad.shade );
}
-#if !DO_PSTIPPLE_IN_DRAW_MODULE
+#if !DO_PSTIPPLE_IN_DRAW_MODULE && !DO_PSTIPPLE_IN_HELPER_MODULE
if (sp->rasterizer->poly_stipple_enable)
- sp_push_quad_first( sp, sp->quad.pstipple );
+ insert_stage_at_head( sp, sp->quad.pstipple );
#endif
}
diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c
index 0ce28f4c6ee..656d001809f 100644
--- a/src/gallium/drivers/softpipe/sp_setup.c
+++ b/src/gallium/drivers/softpipe/sp_setup.c
@@ -568,17 +568,18 @@ tri_persp_coeff(struct setup_context *setup,
static void
setup_fragcoord_coeff(struct setup_context *setup, uint slot)
{
- struct sp_fragment_shader* spfs = setup->softpipe->fs;
+ const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
+
/*X*/
- setup->coef[slot].a0[0] = spfs->pixel_center_integer ? 0.0 : 0.5;
+ setup->coef[slot].a0[0] = fsInfo->pixel_center_integer ? 0.0 : 0.5;
setup->coef[slot].dadx[0] = 1.0;
setup->coef[slot].dady[0] = 0.0;
/*Y*/
setup->coef[slot].a0[1] =
- (spfs->origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0)
- + (spfs->pixel_center_integer ? 0.0 : 0.5);
+ (fsInfo->origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0)
+ + (fsInfo->pixel_center_integer ? 0.0 : 0.5);
setup->coef[slot].dadx[1] = 0.0;
- setup->coef[slot].dady[1] = spfs->origin_lower_left ? -1.0 : 1.0;
+ setup->coef[slot].dady[1] = fsInfo->origin_lower_left ? -1.0 : 1.0;
/*Z*/
setup->coef[slot].a0[2] = setup->posCoef.a0[2];
setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
@@ -599,7 +600,7 @@ static void
setup_tri_coefficients(struct setup_context *setup)
{
struct softpipe_context *softpipe = setup->softpipe;
- const struct sp_fragment_shader *spfs = softpipe->fs;
+ const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
float v[3];
@@ -618,7 +619,7 @@ setup_tri_coefficients(struct setup_context *setup)
/* setup interpolation for all the remaining attributes:
*/
- for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
+ for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
const uint vertSlot = vinfo->attrib[fragSlot].src_index;
uint j;
@@ -632,7 +633,7 @@ setup_tri_coefficients(struct setup_context *setup)
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmid[vertSlot][j],
setup->vmax[vertSlot][j],
- spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
+ fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v);
tri_linear_coeff(setup, &setup->coef[fragSlot], j, v);
}
@@ -642,7 +643,7 @@ setup_tri_coefficients(struct setup_context *setup)
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmid[vertSlot][j],
setup->vmax[vertSlot][j],
- spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
+ fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v);
tri_persp_coeff(setup, &setup->coef[fragSlot], j, v);
}
@@ -654,7 +655,7 @@ setup_tri_coefficients(struct setup_context *setup)
assert(0);
}
- if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
+ if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
/* convert 0 to 1.0 and 1 to -1.0 */
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0;
@@ -939,7 +940,7 @@ setup_line_coefficients(struct setup_context *setup,
const float (*v1)[4])
{
struct softpipe_context *softpipe = setup->softpipe;
- const struct sp_fragment_shader *spfs = softpipe->fs;
+ const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
float area;
@@ -974,7 +975,7 @@ setup_line_coefficients(struct setup_context *setup,
/* setup interpolation for all the remaining attributes:
*/
- for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
+ for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
const uint vertSlot = vinfo->attrib[fragSlot].src_index;
uint j;
@@ -987,7 +988,7 @@ setup_line_coefficients(struct setup_context *setup,
for (j = 0; j < NUM_CHANNELS; j++) {
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmax[vertSlot][j],
- spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
+ fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v);
line_linear_coeff(setup, &setup->coef[fragSlot], j, v);
}
@@ -996,7 +997,7 @@ setup_line_coefficients(struct setup_context *setup,
for (j = 0; j < NUM_CHANNELS; j++) {
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmax[vertSlot][j],
- spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
+ fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v);
line_persp_coeff(setup, &setup->coef[fragSlot], j, v);
}
@@ -1008,7 +1009,7 @@ setup_line_coefficients(struct setup_context *setup,
assert(0);
}
- if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
+ if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
/* convert 0 to 1.0 and 1 to -1.0 */
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0;
@@ -1188,7 +1189,7 @@ sp_setup_point(struct setup_context *setup,
const float (*v0)[4])
{
struct softpipe_context *softpipe = setup->softpipe;
- const struct sp_fragment_shader *spfs = softpipe->fs;
+ const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
const int sizeAttr = setup->softpipe->psize_slot;
const float size
= sizeAttr > 0 ? v0[sizeAttr][0]
@@ -1232,7 +1233,7 @@ sp_setup_point(struct setup_context *setup,
const_coeff(setup, &setup->posCoef, 0, 2);
const_coeff(setup, &setup->posCoef, 0, 3);
- for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
+ for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
const uint vertSlot = vinfo->attrib[fragSlot].src_index;
uint j;
@@ -1255,7 +1256,7 @@ sp_setup_point(struct setup_context *setup,
assert(0);
}
- if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
+ if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
/* convert 0 to 1.0 and 1 to -1.0 */
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0;
@@ -1396,7 +1397,7 @@ sp_setup_prepare(struct setup_context *setup)
struct softpipe_context *sp = setup->softpipe;
if (sp->dirty) {
- softpipe_update_derived(sp);
+ softpipe_update_derived(sp, sp->reduced_api_prim);
}
/* Note: nr_attrs is only used for debugging (vertex printing) */
diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h
index bb19f8cff20..ec4c8cf5e4d 100644
--- a/src/gallium/drivers/softpipe/sp_state.h
+++ b/src/gallium/drivers/softpipe/sp_state.h
@@ -60,34 +60,45 @@ struct tgsi_exec_machine;
struct vertex_info;
-/**
- * Subclass of pipe_shader_state (though it doesn't really need to be).
- *
- * This is starting to look an awful lot like a quad pipeline stage...
- */
-struct sp_fragment_shader {
- struct pipe_shader_state shader;
+struct sp_fragment_shader_variant_key
+{
+ boolean polygon_stipple;
+};
+
+struct sp_fragment_shader_variant
+{
+ const struct tgsi_token *tokens;
+ struct sp_fragment_shader_variant_key key;
struct tgsi_shader_info info;
+ unsigned stipple_sampler_unit;
+
+ /* See comments about this elsewhere */
+#if 0
struct draw_fragment_shader *draw_shader;
+#endif
- boolean origin_lower_left; /**< fragment shader uses lower left position origin? */
- boolean pixel_center_integer; /**< fragment shader uses integer pixel center? */
- boolean color0_writes_all_cbufs; /**< fragment shader writes color0 to all bound cbufs */
- void (*prepare)( const struct sp_fragment_shader *shader,
- struct tgsi_exec_machine *machine,
- struct tgsi_sampler **samplers);
+ void (*prepare)(const struct sp_fragment_shader_variant *shader,
+ struct tgsi_exec_machine *machine,
+ struct tgsi_sampler **samplers);
- /* Run the shader - this interface will get cleaned up in the
- * future:
- */
- unsigned (*run)( const struct sp_fragment_shader *shader,
- struct tgsi_exec_machine *machine,
- struct quad_header *quad );
+ unsigned (*run)(const struct sp_fragment_shader_variant *shader,
+ struct tgsi_exec_machine *machine,
+ struct quad_header *quad);
+ /* Deletes this instance of the object */
+ void (*delete)(struct sp_fragment_shader_variant *shader);
- void (*delete)( struct sp_fragment_shader * );
+ struct sp_fragment_shader_variant *next;
+};
+
+
+/** Subclass of pipe_shader_state */
+struct sp_fragment_shader {
+ struct pipe_shader_state shader;
+ struct sp_fragment_shader_variant *variants;
+ struct draw_fragment_shader *draw_shader;
};
@@ -141,7 +152,7 @@ softpipe_set_framebuffer_state(struct pipe_context *,
const struct pipe_framebuffer_state *);
void
-softpipe_update_derived( struct softpipe_context *softpipe );
+softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim);
void
softpipe_draw_vbo(struct pipe_context *pipe,
@@ -170,4 +181,16 @@ struct vertex_info *
softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe);
+struct sp_fragment_shader_variant *
+softpipe_find_fs_variant(struct softpipe_context *softpipe,
+ struct sp_fragment_shader *fs,
+ const struct sp_fragment_shader_variant_key *key);
+
+
+struct sp_fragment_shader_variant *
+softpipe_find_fs_variant(struct softpipe_context *softpipe,
+ struct sp_fragment_shader *fs,
+ const struct sp_fragment_shader_variant_key *key);
+
+
#endif
diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c
index f9590eb0b24..fd688089a3e 100644
--- a/src/gallium/drivers/softpipe/sp_state_derived.c
+++ b/src/gallium/drivers/softpipe/sp_state_derived.c
@@ -25,8 +25,10 @@
*
**************************************************************************/
+#include "util/u_inlines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
+#include "util/u_pstipple.h"
#include "pipe/p_shader_tokens.h"
#include "draw/draw_context.h"
#include "draw/draw_vertex.h"
@@ -64,7 +66,7 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
if (vinfo->num_attribs == 0) {
/* compute vertex layout now */
- const struct sp_fragment_shader *spfs = softpipe->fs;
+ const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info;
struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
const uint num = draw_num_shader_outputs(softpipe->draw);
uint i;
@@ -84,11 +86,11 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
* from the vertex shader.
*/
vinfo->num_attribs = 0;
- for (i = 0; i < spfs->info.num_inputs; i++) {
+ for (i = 0; i < fsInfo->num_inputs; i++) {
int src;
enum interp_mode interp;
- switch (spfs->info.input_interpolate[i]) {
+ switch (fsInfo->input_interpolate[i]) {
case TGSI_INTERPOLATE_CONSTANT:
interp = INTERP_CONSTANT;
break;
@@ -103,7 +105,7 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
interp = INTERP_LINEAR;
}
- switch (spfs->info.input_semantic_name[i]) {
+ switch (fsInfo->input_semantic_name[i]) {
case TGSI_SEMANTIC_POSITION:
interp = INTERP_POS;
break;
@@ -117,8 +119,8 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
/* this includes texcoords and varying vars */
src = draw_find_shader_output(softpipe->draw,
- spfs->info.input_semantic_name[i],
- spfs->info.input_semantic_index[i]);
+ fsInfo->input_semantic_name[i],
+ fsInfo->input_semantic_index[i]);
draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src);
}
@@ -241,10 +243,101 @@ update_tgsi_samplers( struct softpipe_context *softpipe )
}
+static void
+update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
+{
+ struct sp_fragment_shader_variant_key key;
+
+ memset(&key, 0, sizeof(key));
+
+ if (prim == PIPE_PRIM_TRIANGLES)
+ key.polygon_stipple = softpipe->rasterizer->poly_stipple_enable;
+
+ if (softpipe->fs) {
+ softpipe->fs_variant = softpipe_find_fs_variant(softpipe,
+ softpipe->fs, &key);
+ }
+ else {
+ softpipe->fs_variant = NULL;
+ }
+
+ /* This would be the logical place to pass the fragment shader
+ * to the draw module. However, doing this here, during state
+ * validation, causes problems with the 'draw' module helpers for
+ * wide/AA/stippled lines.
+ * In principle, the draw's fragment shader should be per-variant
+ * but that doesn't work. So we use a single draw fragment shader
+ * per fragment shader, not per variant.
+ */
+#if 0
+ if (softpipe->fs_variant) {
+ draw_bind_fragment_shader(softpipe->draw,
+ softpipe->fs_variant->draw_shader);
+ }
+ else {
+ draw_bind_fragment_shader(softpipe->draw, NULL);
+ }
+#endif
+}
+
+
+/**
+ * This should be called when the polygon stipple pattern changes.
+ * We create a new texture from the stipple pattern and create a new
+ * sampler view.
+ */
+static void
+update_polygon_stipple_pattern(struct softpipe_context *softpipe)
+{
+ struct pipe_resource *tex;
+ struct pipe_sampler_view *view;
+
+ tex = util_pstipple_create_stipple_texture(&softpipe->pipe,
+ softpipe->poly_stipple.stipple);
+ pipe_resource_reference(&softpipe->pstipple.texture, tex);
+
+ view = util_pstipple_create_sampler_view(&softpipe->pipe, tex);
+ pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, view);
+}
+
+
+/**
+ * Should be called when polygon stipple is enabled/disabled or when
+ * the fragment shader changes.
+ * We add/update the fragment sampler and sampler views to sample from
+ * the polygon stipple texture. The texture unit that we use depends on
+ * the fragment shader (we need to use a unit not otherwise used by the
+ * shader).
+ */
+static void
+update_polygon_stipple_enable(struct softpipe_context *softpipe, unsigned prim)
+{
+ if (prim == PIPE_PRIM_TRIANGLES &&
+ softpipe->fs_variant->key.polygon_stipple) {
+ const unsigned unit = softpipe->fs_variant->stipple_sampler_unit;
+
+ assert(unit >= softpipe->num_fragment_samplers);
+
+ /* sampler state */
+ softpipe->fragment_samplers[unit] = softpipe->pstipple.sampler;
+
+ /* sampler view */
+ pipe_sampler_view_reference(&softpipe->fragment_sampler_views[unit],
+ softpipe->pstipple.sampler_view);
+
+ sp_tex_tile_cache_set_sampler_view(softpipe->fragment_tex_cache[unit],
+ softpipe->pstipple.sampler_view);
+
+ softpipe->dirty |= SP_NEW_SAMPLER;
+ }
+}
+
+
/* Hopefully this will remain quite simple, otherwise need to pull in
* something like the state tracker mechanism.
*/
-void softpipe_update_derived( struct softpipe_context *softpipe )
+void
+softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim)
{
struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);
@@ -254,7 +347,24 @@ void softpipe_update_derived( struct softpipe_context *softpipe )
softpipe->tex_timestamp = sp_screen->timestamp;
softpipe->dirty |= SP_NEW_TEXTURE;
}
-
+
+#if DO_PSTIPPLE_IN_HELPER_MODULE
+ if (softpipe->dirty & SP_NEW_STIPPLE)
+ /* before updating samplers! */
+ update_polygon_stipple_pattern(softpipe);
+#endif
+
+ if (softpipe->dirty & (SP_NEW_RASTERIZER |
+ SP_NEW_FS))
+ update_fragment_shader(softpipe, prim);
+
+#if DO_PSTIPPLE_IN_HELPER_MODULE
+ if (softpipe->dirty & (SP_NEW_RASTERIZER |
+ SP_NEW_STIPPLE |
+ SP_NEW_FS))
+ update_polygon_stipple_enable(softpipe, prim);
+#endif
+
if (softpipe->dirty & (SP_NEW_SAMPLER |
SP_NEW_TEXTURE |
SP_NEW_FS |
diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c
index 60331bc4976..16023c990a7 100644
--- a/src/gallium/drivers/softpipe/sp_state_sampler.c
+++ b/src/gallium/drivers/softpipe/sp_state_sampler.c
@@ -373,8 +373,9 @@ softpipe_reset_sampler_variants(struct softpipe_context *softpipe)
}
}
- for (i = 0; i <= softpipe->fs->info.file_max[TGSI_FILE_SAMPLER]; i++) {
+ for (i = 0; i <= softpipe->fs_variant->info.file_max[TGSI_FILE_SAMPLER]; i++) {
if (softpipe->fragment_samplers[i]) {
+ assert(softpipe->fragment_sampler_views[i]->texture);
softpipe->tgsi.frag_samplers_list[i] =
get_sampler_variant( i,
sp_sampler(softpipe->fragment_samplers[i]),
diff --git a/src/gallium/drivers/softpipe/sp_state_shader.c b/src/gallium/drivers/softpipe/sp_state_shader.c
index 3dec5de3cc4..da895270aa9 100644
--- a/src/gallium/drivers/softpipe/sp_state_shader.c
+++ b/src/gallium/drivers/softpipe/sp_state_shader.c
@@ -33,6 +33,7 @@
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
+#include "util/u_pstipple.h"
#include "draw/draw_context.h"
#include "draw/draw_vs.h"
#include "draw/draw_gs.h"
@@ -42,46 +43,105 @@
#include "tgsi/tgsi_parse.h"
+/**
+ * Create a new fragment shader variant.
+ */
+static struct sp_fragment_shader_variant *
+create_fs_variant(struct softpipe_context *softpipe,
+ struct sp_fragment_shader *fs,
+ const struct sp_fragment_shader_variant_key *key)
+{
+ struct sp_fragment_shader_variant *var;
+ struct pipe_shader_state *stipple_fs = NULL, *curfs = &fs->shader;
+ unsigned unit = 0;
+
+ if (key->polygon_stipple) {
+ /* get new shader that implements polygon stippling */
+ stipple_fs = util_pstipple_create_fragment_shader(&softpipe->pipe,
+ curfs, &unit);
+ curfs = stipple_fs;
+ }
+
+ /* codegen, create variant object */
+ var = softpipe_create_fs_variant_sse(softpipe, curfs);
+ if (!var) {
+ var = softpipe_create_fs_variant_exec(softpipe, curfs);
+ }
+
+ if (var) {
+ var->key = *key;
+ var->tokens = tgsi_dup_tokens(curfs->tokens);
+ var->stipple_sampler_unit = unit;
+
+ tgsi_scan_shader(var->tokens, &var->info);
+
+ /* See comments elsewhere about draw fragment shaders */
+#if 0
+ /* draw's fs state */
+ var->draw_shader = draw_create_fragment_shader(softpipe->draw,
+ &fs->shader);
+ if (!var->draw_shader) {
+ var->delete(var);
+ FREE((void *) var->tokens);
+ return NULL;
+ }
+#endif
+
+ /* insert variant into linked list */
+ var->next = fs->variants;
+ fs->variants = var;
+ }
+
+ if (stipple_fs) {
+ free((void *) stipple_fs->tokens);
+ free(stipple_fs);
+ }
+
+ return var;
+}
+
+
+struct sp_fragment_shader_variant *
+softpipe_find_fs_variant(struct softpipe_context *sp,
+ struct sp_fragment_shader *fs,
+ const struct sp_fragment_shader_variant_key *key)
+{
+ struct sp_fragment_shader_variant *var;
+
+ for (var = fs->variants; var; var = var->next) {
+ if (memcmp(&var->key, key, sizeof(*key)) == 0) {
+ /* found it */
+ return var;
+ }
+ }
+
+ return create_fs_variant(sp, fs, key);
+}
+
+
static void *
softpipe_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
- struct sp_fragment_shader *state;
- unsigned i;
+ struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader);
/* debug */
if (softpipe->dump_fs)
tgsi_dump(templ->tokens, 0);
- /* codegen */
- state = softpipe_create_fs_sse( softpipe, templ );
- if (!state) {
- state = softpipe_create_fs_exec( softpipe, templ );
- }
-
- if (!state)
- return NULL;
+ /* we need to keep a local copy of the tokens */
+ state->shader.tokens = tgsi_dup_tokens(templ->tokens);
/* draw's fs state */
- state->draw_shader = draw_create_fragment_shader(softpipe->draw, templ);
+ state->draw_shader = draw_create_fragment_shader(softpipe->draw,
+ &state->shader);
if (!state->draw_shader) {
- state->delete( state );
+ FREE((void *) state->shader.tokens);
+ FREE(state);
return NULL;
}
- /* get/save the summary info for this shader */
- tgsi_scan_shader(templ->tokens, &state->info);
-
- for (i = 0; i < state->info.num_properties; ++i) {
- if (state->info.properties[i].name == TGSI_PROPERTY_FS_COORD_ORIGIN)
- state->origin_lower_left = state->info.properties[i].data[0];
- else if (state->info.properties[i].name == TGSI_PROPERTY_FS_COORD_PIXEL_CENTER)
- state->pixel_center_integer = state->info.properties[i].data[0];
- else if (state->info.properties[i].name == TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS)
- state->color0_writes_all_cbufs = state->info.properties[i].data[0];
- }
-
return state;
}
@@ -90,6 +150,7 @@ static void
softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
+ struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs;
if (softpipe->fs == fs)
return;
@@ -98,8 +159,14 @@ softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
softpipe->fs = fs;
- draw_bind_fragment_shader(softpipe->draw,
- (softpipe->fs ? softpipe->fs->draw_shader : NULL));
+ if (fs == NULL)
+ softpipe->fs_variant = NULL;
+
+ if (state)
+ draw_bind_fragment_shader(softpipe->draw,
+ state->draw_shader);
+ else
+ draw_bind_fragment_shader(softpipe->draw, NULL);
softpipe->dirty |= SP_NEW_FS;
}
@@ -110,8 +177,9 @@ softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_fragment_shader *state = fs;
+ struct sp_fragment_shader_variant *var, *next_var;
- assert(fs != softpipe_context(pipe)->fs);
+ assert(fs != softpipe->fs);
if (softpipe->fs_machine->Tokens == state->shader.tokens) {
/* unbind the shader from the tgsi executor if we're
@@ -120,9 +188,23 @@ softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
tgsi_exec_machine_bind_shader(softpipe->fs_machine, NULL, 0, NULL);
}
+ /* delete variants */
+ for (var = state->variants; var; var = next_var) {
+ next_var = var->next;
+
+ assert(var != softpipe->fs_variant);
+
+ /* See comments elsewhere about draw fragment shaders */
+#if 0
+ draw_delete_fragment_shader(softpipe->draw, var->draw_shader);
+#endif
+
+ var->delete(var);
+ }
+
draw_delete_fragment_shader(softpipe->draw, state->draw_shader);
- state->delete( state );
+ FREE((void *) state->shader.tokens);
}