summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2011-07-13 10:58:01 -0600
committerBrian Paul <[email protected]>2011-09-23 07:58:47 -0600
commit2f40e4aac7ab79deb06ff6ab9ae03a896d7a9169 (patch)
treea9223f69183aa85899b538ef08f10dad91ffdb6f /src
parent9a41ecaddddb2f371e207901ae4d86918049c5aa (diff)
svga: implement point sprite suppport
Emit the SVGA3D_RS_POINTSPRITEENABLE render state. When sprite_coord_mode=PIPE_SPRITE_COORD_LOWER_LEFT emit extra frag shader code to invert the Y coordinate of the incoming texcoord.
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/svga/svga_context.h1
-rw-r--r--src/gallium/drivers/svga/svga_pipe_rasterizer.c1
-rw-r--r--src/gallium/drivers/svga/svga_state_fs.c9
-rw-r--r--src/gallium/drivers/svga/svga_state_rss.c1
-rw-r--r--src/gallium/drivers/svga/svga_tgsi.h2
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_decl_sm30.c31
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_emit.h5
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_insn.c73
8 files changed, 119 insertions, 4 deletions
diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h
index f8c1ab40345..a03a81749bb 100644
--- a/src/gallium/drivers/svga/svga_context.h
+++ b/src/gallium/drivers/svga/svga_context.h
@@ -141,6 +141,7 @@ struct svga_rasterizer_state {
unsigned multisampleantialias:1;
unsigned antialiasedlineenable:1;
unsigned lastpixel:1;
+ unsigned pointsprite:1;
unsigned linepattern;
diff --git a/src/gallium/drivers/svga/svga_pipe_rasterizer.c b/src/gallium/drivers/svga/svga_pipe_rasterizer.c
index 4a1a37f1765..a18845e3b7c 100644
--- a/src/gallium/drivers/svga/svga_pipe_rasterizer.c
+++ b/src/gallium/drivers/svga/svga_pipe_rasterizer.c
@@ -89,6 +89,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
rast->multisampleantialias = templ->multisample;
rast->antialiasedlineenable = templ->line_smooth;
rast->lastpixel = templ->line_last_pixel;
+ rast->pointsprite = templ->sprite_coord_enable != 0x0;
rast->pointsize = templ->point_size;
rast->hw_unfilled = PIPE_POLYGON_MODE_FILL;
diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c
index 9c04adec8ee..8a50bfd344a 100644
--- a/src/gallium/drivers/svga/svga_state_fs.c
+++ b/src/gallium/drivers/svga/svga_state_fs.c
@@ -179,6 +179,15 @@ static int make_fs_key( const struct svga_context *svga,
}
}
+ /* sprite coord gen state */
+ for (i = 0; i < svga->curr.num_samplers; ++i) {
+ key->tex[i].sprite_texgen =
+ svga->curr.rast->templ.sprite_coord_enable & (1 << i);
+ }
+
+ key->sprite_origin_lower_left = (svga->curr.rast->templ.sprite_coord_mode
+ == PIPE_SPRITE_COORD_LOWER_LEFT);
+
return 0;
}
diff --git a/src/gallium/drivers/svga/svga_state_rss.c b/src/gallium/drivers/svga/svga_state_rss.c
index 28f32793742..a37e1f8128b 100644
--- a/src/gallium/drivers/svga/svga_state_rss.c
+++ b/src/gallium/drivers/svga/svga_state_rss.c
@@ -217,6 +217,7 @@ static int emit_rss( struct svga_context *svga,
/* XXX still need to set this? */
EMIT_RS_FLOAT( svga, 0.0, POINTSIZEMIN, fail );
EMIT_RS_FLOAT( svga, SVGA_MAX_POINTSIZE, POINTSIZEMAX, fail );
+ EMIT_RS( svga, curr->pointsprite, POINTSPRITEENABLE, fail);
}
if (dirty & (SVGA_NEW_RAST | SVGA_NEW_FRAME_BUFFER | SVGA_NEW_NEED_PIPELINE))
diff --git a/src/gallium/drivers/svga/svga_tgsi.h b/src/gallium/drivers/svga/svga_tgsi.h
index 7ea909c37bf..bd63bf5c264 100644
--- a/src/gallium/drivers/svga/svga_tgsi.h
+++ b/src/gallium/drivers/svga/svga_tgsi.h
@@ -52,12 +52,14 @@ struct svga_fs_compile_key
unsigned white_fragments:1;
unsigned num_textures:8;
unsigned num_unnormalized_coords:8;
+ unsigned sprite_origin_lower_left:1;
struct {
unsigned compare_mode:1;
unsigned compare_func:3;
unsigned unnormalized:1;
unsigned width_height_idx:7;
unsigned texture_target:8;
+ unsigned sprite_texgen:1;
} tex[PIPE_MAX_SAMPLERS];
};
diff --git a/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c b/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c
index ed4b000e4f3..6f162ea7e33 100644
--- a/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c
+++ b/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c
@@ -234,7 +234,36 @@ static boolean ps30_input( struct svga_shader_emitter *emit,
emit->input_map[idx] = src_register( SVGA3DREG_INPUT, emit->ps30_input_count++ );
reg = dst( emit->input_map[idx] );
- return emit_decl( emit, reg, usage, index );
+ if (!emit_decl( emit, reg, usage, index ))
+ return FALSE;
+
+ if (semantic.Name == TGSI_SEMANTIC_GENERIC &&
+ emit->key.fkey.sprite_origin_lower_left &&
+ index >= 1 &&
+ emit->key.fkey.tex[index - 1].sprite_texgen) {
+ /* This is a sprite texture coord with lower-left origin.
+ * We need to invert the texture T coordinate since the SVGA3D
+ * device only supports an upper-left origin.
+ */
+ unsigned unit = index - 1;
+
+ emit->inverted_texcoords |= (1 << unit);
+
+ /* save original texcoord reg */
+ emit->ps_true_texcoord[unit] = emit->input_map[idx];
+
+ /* this temp register will be the results of the MAD instruction */
+ emit->ps_inverted_texcoord[unit] =
+ src_register(SVGA3DREG_TEMP, emit->nr_hw_temp);
+ emit->nr_hw_temp++;
+
+ emit->ps_inverted_texcoord_input[unit] = idx;
+
+ /* replace input_map entry with the temp register */
+ emit->input_map[idx] = emit->ps_inverted_texcoord[unit];
+ }
+
+ return TRUE;
}
}
diff --git a/src/gallium/drivers/svga/svga_tgsi_emit.h b/src/gallium/drivers/svga/svga_tgsi_emit.h
index b1300dc8ecd..fca396e656e 100644
--- a/src/gallium/drivers/svga/svga_tgsi_emit.h
+++ b/src/gallium/drivers/svga/svga_tgsi_emit.h
@@ -94,6 +94,11 @@ struct svga_shader_emitter
boolean created_sincos_consts;
int sincos_consts_idx;
+ unsigned inverted_texcoords; /**< bitmask of which texcoords are flipped */
+ struct src_register ps_true_texcoord[PIPE_MAX_ATTRIBS];
+ struct src_register ps_inverted_texcoord[PIPE_MAX_ATTRIBS];
+ unsigned ps_inverted_texcoord_input[PIPE_MAX_ATTRIBS];
+
unsigned label[32];
unsigned nr_labels;
diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c
index 10688accdaa..6f03e61db55 100644
--- a/src/gallium/drivers/svga/svga_tgsi_insn.c
+++ b/src/gallium/drivers/svga/svga_tgsi_insn.c
@@ -27,6 +27,7 @@
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_parse.h"
#include "util/u_memory.h"
+#include "util/u_math.h"
#include "svga_tgsi_emit.h"
#include "svga_context.h"
@@ -623,8 +624,11 @@ create_zero_immediate( struct svga_shader_emitter *emit )
{
unsigned idx = emit->nr_hw_float_const++;
+ /* Emit the constant (0, 0, -1, 1) and use swizzling to generate
+ * other useful vectors.
+ */
if (!emit_def_const( emit, SVGA3D_CONST_TYPE_FLOAT,
- idx, 0, 0, 0, 1 ))
+ idx, 0, 0, -1, 1 ))
return FALSE;
emit->zero_immediate_idx = idx;
@@ -731,8 +735,20 @@ get_zero_immediate( struct svga_shader_emitter *emit )
{
assert(emit->created_zero_immediate);
assert(emit->zero_immediate_idx >= 0);
- return src_register( SVGA3DREG_CONST,
- emit->zero_immediate_idx );
+ return swizzle(src_register( SVGA3DREG_CONST,
+ emit->zero_immediate_idx),
+ 0, 0, 0, 3);
+}
+
+/* returns {1, 1, 1, -1} immediate */
+static INLINE struct src_register
+get_pos_neg_one_immediate( struct svga_shader_emitter *emit )
+{
+ assert(emit->created_zero_immediate);
+ assert(emit->zero_immediate_idx >= 0);
+ return swizzle(src_register( SVGA3DREG_CONST,
+ emit->zero_immediate_idx),
+ 3, 3, 3, 2);
}
/* returns the loop const */
@@ -2849,6 +2865,50 @@ static boolean emit_frontface( struct svga_shader_emitter *emit )
return TRUE;
}
+
+/**
+ * Emit code to invert the T component of the incoming texture coordinate.
+ * This is used for drawing point sprites when
+ * pipe_rasterizer_state::sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT.
+ */
+static boolean emit_inverted_texcoords( struct svga_shader_emitter *emit )
+{
+ struct src_register zero = get_zero_immediate(emit);
+ struct src_register pos_neg_one = get_pos_neg_one_immediate( emit );
+ unsigned inverted_texcoords = emit->inverted_texcoords;
+
+ while (inverted_texcoords) {
+ const unsigned unit = ffs(inverted_texcoords) - 1;
+
+ assert(emit->inverted_texcoords & (1 << unit));
+
+ assert(unit < Elements(emit->ps_true_texcoord));
+
+ assert(unit < Elements(emit->ps_inverted_texcoord_input));
+
+ assert(emit->ps_inverted_texcoord_input[unit]
+ < Elements(emit->input_map));
+
+ /* inverted = coord * (1, -1, 1, 1) + (0, 1, 0, 0) */
+ if (!submit_op3(emit,
+ inst_token(SVGA3DOP_MAD),
+ dst(emit->ps_inverted_texcoord[unit]),
+ emit->ps_true_texcoord[unit],
+ swizzle(pos_neg_one, 0, 3, 0, 0), /* (1, -1, 1, 1) */
+ swizzle(zero, 0, 3, 0, 0))) /* (0, 1, 0, 0) */
+ return FALSE;
+
+ /* Reassign the input_map entry to the new texcoord register */
+ emit->input_map[emit->ps_inverted_texcoord_input[unit]] =
+ emit->ps_inverted_texcoord[unit];
+
+ inverted_texcoords &= ~(1 << unit);
+ }
+
+ return TRUE;
+}
+
+
static INLINE boolean
needs_to_create_zero( struct svga_shader_emitter *emit )
{
@@ -2871,6 +2931,9 @@ needs_to_create_zero( struct svga_shader_emitter *emit )
emit->info.opcode_count[TGSI_OPCODE_SSG] >= 1 ||
emit->info.opcode_count[TGSI_OPCODE_LIT] >= 1)
return TRUE;
+
+ if (emit->inverted_texcoords)
+ return TRUE;
}
if (emit->unit == PIPE_SHADER_VERTEX) {
@@ -3036,6 +3099,10 @@ static boolean svga_shader_emit_helpers( struct svga_shader_emitter *emit )
if (!emit_frontface( emit ))
return FALSE;
}
+ if (emit->inverted_texcoords) {
+ if (!emit_inverted_texcoords( emit ))
+ return FALSE;
+ }
}
return TRUE;