diff options
author | Brian Paul <[email protected]> | 2011-07-13 10:58:01 -0600 |
---|---|---|
committer | Brian Paul <[email protected]> | 2011-09-23 07:58:47 -0600 |
commit | 2f40e4aac7ab79deb06ff6ab9ae03a896d7a9169 (patch) | |
tree | a9223f69183aa85899b538ef08f10dad91ffdb6f | |
parent | 9a41ecaddddb2f371e207901ae4d86918049c5aa (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.
-rw-r--r-- | src/gallium/drivers/svga/svga_context.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_pipe_rasterizer.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_state_fs.c | 9 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_state_rss.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_tgsi.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_tgsi_decl_sm30.c | 31 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_tgsi_emit.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_tgsi_insn.c | 73 |
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; |