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;
}
}
#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"
{
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;
{
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 */
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 )
{
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) {
if (!emit_frontface( emit ))
return FALSE;
}
+ if (emit->inverted_texcoords) {
+ if (!emit_inverted_texcoords( emit ))
+ return FALSE;
+ }
}
return TRUE;