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.
This commit is contained in:
Brian Paul 2011-07-13 10:58:01 -06:00
parent 9a41ecaddd
commit 2f40e4aac7
8 changed files with 119 additions and 4 deletions

View file

@ -141,6 +141,7 @@ struct svga_rasterizer_state {
unsigned multisampleantialias:1;
unsigned antialiasedlineenable:1;
unsigned lastpixel:1;
unsigned pointsprite:1;
unsigned linepattern;

View file

@ -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;

View file

@ -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;
}

View file

@ -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))

View file

@ -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];
};

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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;