#include "i915_context.h"
#include "i915_fpc.h"
-#include "pipe/tgsi/core/tgsi_token.h"
-#include "pipe/tgsi/core/tgsi_parse.h"
+#include "pipe/tgsi/exec/tgsi_token.h"
+#include "pipe/tgsi/exec/tgsi_parse.h"
+
+#include "pipe/draw/draw_vertex.h"
+
/**
* Simple pass-through fragment shader to use when we don't have
+/**
+ * component-wise negation of ureg
+ */
+static INLINE int
+negate(int reg, int x, int y, int z, int w)
+{
+ /* Another neat thing about the UREG representation */
+ return reg ^ (((x & 1) << UREG_CHANNEL_X_NEGATE_SHIFT) |
+ ((y & 1) << UREG_CHANNEL_Y_NEGATE_SHIFT) |
+ ((z & 1) << UREG_CHANNEL_Z_NEGATE_SHIFT) |
+ ((w & 1) << UREG_CHANNEL_W_NEGATE_SHIFT));
+}
+
+
static void
i915_use_passthrough_shader(struct i915_context *i915)
{
fprintf(stderr, "**** Using i915 pass-through fragment shader\n");
i915->current.program = (uint *) malloc(sizeof(passthrough));
- memcpy(i915->current.program, passthrough, sizeof(passthrough));
- i915->current.program_len = Elements(passthrough);
+ if (i915->current.program) {
+ memcpy(i915->current.program, passthrough, sizeof(passthrough));
+ i915->current.program_len = Elements(passthrough);
+ }
- i915->current.constants = NULL;
- i915->current.num_constants = 0;
+ i915->current.num_constants[PIPE_SHADER_FRAGMENT] = 0;
+ i915->current.num_user_constants[PIPE_SHADER_FRAGMENT] = 0;
}
src_vector(struct i915_fp_compile *p,
const struct tgsi_full_src_register *source)
{
- const uint index = source->SrcRegister.Index;
- uint src;
+ uint index = source->SrcRegister.Index;
+ uint src, sem_name, sem_ind;
switch (source->SrcRegister.File) {
case TGSI_FILE_TEMPORARY:
*
* We also use a texture coordinate to pass wpos when possible.
*/
- switch (index) {
- case FRAG_ATTRIB_WPOS:
+
+ /* use vertex format info to map a slot number to a VF attrib */
+ assert(index < p->vertex_info->num_attribs);
+
+ sem_name = p->input_semantic_name[index];
+ sem_ind = p->input_semantic_index[index];
+
+ switch (sem_name) {
+ case TGSI_SEMANTIC_POSITION:
+ printf("SKIP SEM POS\n");
+ /*
+ assert(p->wpos_tex != -1);
src = i915_emit_decl(p, REG_TYPE_T, p->wpos_tex, D0_CHANNEL_ALL);
+ */
break;
- case FRAG_ATTRIB_COL0:
- src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL);
- break;
- case FRAG_ATTRIB_COL1:
- src = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_XYZ);
- src = swizzle(src, X, Y, Z, ONE);
+ case TGSI_SEMANTIC_COLOR:
+ if (sem_ind == 0) {
+ src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL);
+ }
+ else {
+ /* secondary color */
+ assert(sem_ind == 1);
+ src = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_XYZ);
+ src = swizzle(src, X, Y, Z, ONE);
+ }
break;
- case FRAG_ATTRIB_FOGC:
+ case TGSI_SEMANTIC_FOG:
src = i915_emit_decl(p, REG_TYPE_T, T_FOG_W, D0_CHANNEL_W);
src = swizzle(src, W, W, W, W);
break;
- case FRAG_ATTRIB_TEX0:
- case FRAG_ATTRIB_TEX1:
- case FRAG_ATTRIB_TEX2:
- case FRAG_ATTRIB_TEX3:
- case FRAG_ATTRIB_TEX4:
- case FRAG_ATTRIB_TEX5:
- case FRAG_ATTRIB_TEX6:
- case FRAG_ATTRIB_TEX7:
- src = i915_emit_decl(p, REG_TYPE_T,
- T_TEX0 + (index - FRAG_ATTRIB_TEX0),
- D0_CHANNEL_ALL);
+ case TGSI_SEMANTIC_GENERIC:
+ /* usually a texcoord */
+ src = i915_emit_decl(p, REG_TYPE_T, T_TEX0 + sem_ind, D0_CHANNEL_ALL);
break;
-
default:
i915_program_error(p, "Bad source->Index");
return 0;
}
/* no abs() or post-abs negation */
+#if 0
+ /* XXX assertions disabled to allow arbfplight.c to run */
+ /* XXX enable these assertions, or fix things */
assert(!source->SrcRegisterExtMod.Absolute);
assert(!source->SrcRegisterExtMod.Negate);
-
+#endif
return src;
}
{
switch (dest->DstRegister.File) {
case TGSI_FILE_OUTPUT:
- switch (dest->DstRegister.Index) {
- case 1: /*COLOR*/ /*FRAG_RESULT_COLR:*/
- return UREG(REG_TYPE_OC, 0);
- case 0: /*DEPTH*/ /*FRAG_RESULT_DEPR:*/
- return UREG(REG_TYPE_OD, 0);
- default:
- i915_program_error(p, "Bad inst->DstReg.Index");
- return 0;
+ {
+ uint sem_name = p->output_semantic_name[dest->DstRegister.Index];
+ switch (sem_name) {
+ case TGSI_SEMANTIC_POSITION:
+ return UREG(REG_TYPE_OD, 0);
+ case TGSI_SEMANTIC_COLOR:
+ return UREG(REG_TYPE_OC, 0);
+ default:
+ i915_program_error(p, "Bad inst->DstReg.Index/semantics");
+ return 0;
+ }
}
case TGSI_FILE_TEMPORARY:
return UREG(REG_TYPE_R, dest->DstRegister.Index);
swizzle(src1, ONE, Y, ONE, W), 0);
break;
+ case TGSI_OPCODE_END:
+ /* no-op */
+ break;
+
case TGSI_OPCODE_EX2:
src0 = src_vector(p, &inst->FullSrcRegisters[0]);
switch( parse.FullToken.Token.Type ) {
case TGSI_TOKEN_TYPE_DECLARATION:
- /* XXX no-op? */
+ if (parse.FullToken.FullDeclaration.Declaration.File
+ == TGSI_FILE_INPUT) {
+ /* save input register info for use in src_vector() */
+ uint ind, sem, semi;
+ ind = parse.FullToken.FullDeclaration.u.DeclarationRange.First;
+ sem = parse.FullToken.FullDeclaration.Semantic.SemanticName;
+ semi = parse.FullToken.FullDeclaration.Semantic.SemanticIndex;
+ /*printf("FS Input DECL [%u] sem %u\n", ind, sem);*/
+ p->input_semantic_name[ind] = sem;
+ p->input_semantic_index[ind] = semi;
+ }
+ else if (parse.FullToken.FullDeclaration.Declaration.File
+ == TGSI_FILE_OUTPUT) {
+ /* save output register info for use in get_result_vector() */
+ uint ind, sem, semi;
+ ind = parse.FullToken.FullDeclaration.u.DeclarationRange.First;
+ sem = parse.FullToken.FullDeclaration.Semantic.SemanticName;
+ semi = parse.FullToken.FullDeclaration.Semantic.SemanticIndex;
+ /*printf("FS Output DECL [%u] sem %u\n", ind, sem);*/
+ p->output_semantic_name[ind] = sem;
+ p->output_semantic_index[ind] = semi;
+ }
break;
case TGSI_TOKEN_TYPE_IMMEDIATE:
static struct i915_fp_compile *
i915_init_compile(struct i915_context *i915,
- struct pipe_shader_state *fs)
+ const struct pipe_shader_state *fs)
{
struct i915_fp_compile *p = CALLOC_STRUCT(i915_fp_compile);
- p->shader = &i915->fs;
+ p->shader = i915->fs;
+
+ p->vertex_info = &i915->current.vertex_info;
- /* a bit of a hack, need to improve constant buffer infrastructure */
- if (i915->fs.constants)
- p->constants = i915->fs.constants;
- else
- p->constants = &i915->temp_constants;
+ /* new constants found during translation get appended after the
+ * user-provided constants.
+ */
+ p->constants = i915->current.constants[PIPE_SHADER_FRAGMENT];
+ p->num_constants = i915->current.num_user_constants[PIPE_SHADER_FRAGMENT];
p->nr_tex_indirect = 1; /* correct? */
p->nr_tex_insn = 0;
return p;
}
+
/* Copy compile results to the fragment program struct and destroy the
* compilation context.
*/
if (p->nr_decl_insn > I915_MAX_DECL_INSN)
i915_program_error(p, "Exceeded max DECL instructions");
+ /* free old program, if present */
+ if (i915->current.program) {
+ free(i915->current.program);
+ i915->current.program_len = 0;
+ }
+
if (p->error) {
p->NumNativeInstructions = 0;
p->NumNativeAluInstructions = 0;
i915_use_passthrough_shader(i915);
}
else {
- p->NumNativeInstructions = (p->nr_alu_insn +
- p->nr_tex_insn +
- p->nr_decl_insn);
+ p->NumNativeInstructions
+ = p->nr_alu_insn + p->nr_tex_insn + p->nr_decl_insn;
p->NumNativeAluInstructions = p->nr_alu_insn;
p->NumNativeTexInstructions = p->nr_tex_insn;
p->NumNativeTexIndirections = p->nr_tex_indirect;
*/
i915->current.program
= (uint *) malloc((program_size + decl_size) * sizeof(uint));
- i915->current.program_len = program_size + decl_size;
+ if (i915->current.program) {
+ i915->current.program_len = program_size + decl_size;
- memcpy(i915->current.program,
- p->declarations,
- decl_size * sizeof(uint));
+ memcpy(i915->current.program,
+ p->declarations,
+ decl_size * sizeof(uint));
- memcpy(i915->current.program + decl_size,
- p->program,
- program_size * sizeof(uint));
+ memcpy(i915->current.program + decl_size,
+ p->program,
+ program_size * sizeof(uint));
+ }
- i915->current.constants = (uint *) p->constants->constant;
- i915->current.num_constants = p->constants->nr_constants;
+ /* update number of constants */
+ i915->current.num_constants[PIPE_SHADER_FRAGMENT] = p->num_constants;
+ assert(i915->current.num_constants[PIPE_SHADER_FRAGMENT]
+ >= i915->current.num_user_constants[PIPE_SHADER_FRAGMENT]);
}
/* Release the compilation struct:
static void
i915_find_wpos_space(struct i915_fp_compile *p)
{
- const uint inputs = p->shader->inputs_read;
+#if 0
+ const uint inputs
+ = p->shader->inputs_read | (1 << TGSI_ATTRIB_POS); /*XXX hack*/
uint i;
p->wpos_tex = -1;
- if (inputs & FRAG_BIT_WPOS) {
+ if (inputs & (1 << TGSI_ATTRIB_POS)) {
for (i = 0; i < I915_TEX_UNITS; i++) {
- if ((inputs & (FRAG_BIT_TEX0 << i)) == 0) {
+ if ((inputs & (1 << (TGSI_ATTRIB_TEX0 + i))) == 0) {
p->wpos_tex = i;
return;
}
i915_program_error(p, "No free texcoord for wpos value");
}
+#else
+ if (p->shader->input_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
+ /* frag shader using the fragment position input */
+#if 0
+ assert(0);
+#endif
+ }
+#endif
}
static void
i915_fixup_depth_write(struct i915_fp_compile *p)
{
- if (p->shader->outputs_written & (1<<FRAG_RESULT_DEPR)) {
- uint depth = UREG(REG_TYPE_OD, 0);
+ /* XXX assuming pos/depth is always in output[0] */
+ if (p->shader->output_semantic_name[0] == TGSI_SEMANTIC_POSITION) {
+ const uint depth = UREG(REG_TYPE_OD, 0);
i915_emit_arith(p,
- A0_MOV,
- depth, A0_DEST_CHANNEL_W, 0,
- swizzle(depth, X, Y, Z, Z), 0, 0);
+ A0_MOV, /* opcode */
+ depth, /* dest reg */
+ A0_DEST_CHANNEL_W, /* write mask */
+ 0, /* saturate? */
+ swizzle(depth, X, Y, Z, Z), /* src0 */
+ 0, 0 /* src1, src2 */);
}
}
void
i915_translate_fragment_program( struct i915_context *i915 )
{
- struct i915_fp_compile *p = i915_init_compile(i915, &i915->fs);
- const struct tgsi_token *tokens = i915->fs.tokens;
+ struct i915_fp_compile *p = i915_init_compile(i915, i915->fs);
+ const struct tgsi_token *tokens = i915->fs->tokens;
i915_find_wpos_space(p);