/** * TGSI transform prolog callback. */ static void aa_transform_prolog(struct tgsi_transform_context *ctx) { struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; uint i; /* find free sampler */ aactx->freeSampler = free_bit(aactx->samplersUsed); if (aactx->freeSampler >= PIPE_MAX_SAMPLERS) aactx->freeSampler = PIPE_MAX_SAMPLERS - 1; /* find two free temp regs */ for (i = 0; i < 32; i++) { if ((aactx->tempsUsed & (1 << i)) == 0) { /* found a free temp */ if (aactx->colorTemp < 0) aactx->colorTemp = i; else if (aactx->texTemp < 0) aactx->texTemp = i; else break; } } assert(aactx->colorTemp >= 0); assert(aactx->texTemp >= 0); /* declare new generic input/texcoord */ tgsi_transform_input_decl(ctx, aactx->maxInput + 1, TGSI_SEMANTIC_GENERIC, aactx->maxGeneric + 1, TGSI_INTERPOLATE_LINEAR); /* declare new sampler */ tgsi_transform_sampler_decl(ctx, aactx->freeSampler); /* declare new temp regs */ tgsi_transform_temp_decl(ctx, aactx->texTemp); tgsi_transform_temp_decl(ctx, aactx->colorTemp); }
static void transform_instr(struct tgsi_transform_context *tctx, struct tgsi_full_instruction *current_inst) { struct tgsi_atifs_transform *ctx = tgsi_atifs_transform(tctx); if (ctx->first_instruction_emitted) goto transform_inst; ctx->first_instruction_emitted = true; if (ctx->key->fog) { /* add a new temp for the fog factor */ ctx->fog_factor_temp = ctx->info.file_max[TGSI_FILE_TEMPORARY] + 1; tgsi_transform_temp_decl(tctx, ctx->fog_factor_temp); /* add immediates for clamp */ ctx->fog_clamp_imm = ctx->info.immediate_count; tgsi_transform_immediate_decl(tctx, 1.0f, 0.0f, 0.0f, 0.0f); } transform_inst: if (current_inst->Instruction.Opcode == TGSI_OPCODE_TEX) { /* fix texture target */ unsigned newtarget = ctx->key->texture_targets[current_inst->Src[1].Register.Index]; if (newtarget) current_inst->Texture.Texture = newtarget; } else if (ctx->key->fog && current_inst->Instruction.Opcode == TGSI_OPCODE_MOV && current_inst->Dst[0].Register.File == TGSI_FILE_OUTPUT) { struct tgsi_full_instruction inst; unsigned i; int fogc_index = -1; int reg0_index = current_inst->Src[0].Register.Index; /* find FOGC input */ for (i = 0; i < ctx->info.num_inputs; i++) { if (ctx->info.input_semantic_name[i] == TGSI_SEMANTIC_FOG) { fogc_index = i; break; } } if (fogc_index < 0) { /* should never be reached, because fog coord input is always declared */ tctx->emit_instruction(tctx, current_inst); return; } /* compute the 1 component fog factor f */ if (ctx->key->fog == 1) { /* LINEAR formula: f = (end - z) / (end - start) * with optimized parameters: * f = MAD(fogcoord, oparams.x, oparams.y) */ inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_MAD; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 3; SET_SRC(&inst, 0, TGSI_FILE_INPUT, fogc_index, X, Y, Z, W); SET_SRC(&inst, 1, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI, X, X, X, X); SET_SRC(&inst, 2, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI, Y, Y, Y, Y); tctx->emit_instruction(tctx, &inst); } else if (ctx->key->fog == 2) { /* EXP formula: f = exp(-dens * z) * with optimized parameters: * f = MUL(fogcoord, oparams.z); f= EX2(-f) */ inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_MUL; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 2; SET_SRC(&inst, 0, TGSI_FILE_INPUT, fogc_index, X, Y, Z, W); SET_SRC(&inst, 1, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI, Z, Z, Z, Z); tctx->emit_instruction(tctx, &inst); inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_EX2; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 1; SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); inst.Src[0].Register.Negate = 1; tctx->emit_instruction(tctx, &inst); } else if (ctx->key->fog == 3) { /* EXP2 formula: f = exp(-(dens * z)^2) * with optimized parameters: * f = MUL(fogcoord, oparams.w); f=MUL(f, f); f= EX2(-f) */ inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_MUL; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 2; SET_SRC(&inst, 0, TGSI_FILE_INPUT, fogc_index, X, Y, Z, W); SET_SRC(&inst, 1, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI, W, W, W, W); tctx->emit_instruction(tctx, &inst); inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_MUL; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 2; SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); SET_SRC(&inst, 1, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); tctx->emit_instruction(tctx, &inst); inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_EX2; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 1; SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); inst.Src[0].Register.Negate ^= 1; tctx->emit_instruction(tctx, &inst); } /* f = CLAMP(f, 0.0, 1.0) */ inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_CLAMP; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = ctx->fog_factor_temp; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 3; SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, Y, Z, W); SET_SRC(&inst, 1, TGSI_FILE_IMMEDIATE, ctx->fog_clamp_imm, Y, Y, Y, Y); // 0.0 SET_SRC(&inst, 2, TGSI_FILE_IMMEDIATE, ctx->fog_clamp_imm, X, X, X, X); // 1.0 tctx->emit_instruction(tctx, &inst); /* REG0 = LRP(f, REG0, fogcolor) */ inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = TGSI_OPCODE_LRP; inst.Instruction.NumDstRegs = 1; inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; inst.Dst[0].Register.Index = reg0_index; inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; inst.Instruction.NumSrcRegs = 3; SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->fog_factor_temp, X, X, X, Y); SET_SRC(&inst, 1, TGSI_FILE_TEMPORARY, reg0_index, X, Y, Z, W); SET_SRC(&inst, 2, TGSI_FILE_CONSTANT, MAX_NUM_FRAGMENT_CONSTANTS_ATI + 1, X, Y, Z, W); tctx->emit_instruction(tctx, &inst); } tctx->emit_instruction(tctx, current_inst); }
/** * TGSI transform callback. * Insert new declarations and instructions before first instruction. */ static void aa_transform_prolog(struct tgsi_transform_context *ctx) { /* emit our new declarations before the first instruction */ struct aa_transform_context *aactx = (struct aa_transform_context *) ctx; struct tgsi_full_instruction newInst; const int texInput = aactx->maxInput + 1; int tmp0; uint i; /* find two free temp regs */ for (i = 0; i < 32; i++) { if ((aactx->tempsUsed & (1 << i)) == 0) { /* found a free temp */ if (aactx->tmp0 < 0) aactx->tmp0 = i; else if (aactx->colorTemp < 0) aactx->colorTemp = i; else break; } } assert(aactx->colorTemp != aactx->tmp0); tmp0 = aactx->tmp0; /* declare new generic input/texcoord */ tgsi_transform_input_decl(ctx, texInput, TGSI_SEMANTIC_GENERIC, aactx->maxGeneric + 1, TGSI_INTERPOLATE_LINEAR); /* declare new temp regs */ tgsi_transform_temp_decl(ctx, tmp0); tgsi_transform_temp_decl(ctx, aactx->colorTemp); /* * Emit code to compute fragment coverage, kill if outside point radius * * Temp reg0 usage: * t0.x = distance of fragment from center point * t0.y = boolean, is t0.x > 1.0, also misc temp usage * t0.z = temporary for computing 1/(1-k) value * t0.w = final coverage value */ /* MUL t0.xy, tex, tex; # compute x^2, y^2 */ tgsi_transform_op2_inst(ctx, TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_XY, TGSI_FILE_INPUT, texInput, TGSI_FILE_INPUT, texInput); /* ADD t0.x, t0.x, t0.y; # x^2 + y^2 */ tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_ADD, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_X, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_X, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Y); #if NORMALIZE /* OPTIONAL normalization of length */ /* RSQ t0.x, t0.x; */ tgsi_transform_op1_inst(ctx, TGSI_OPCODE_RSQ, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_X, TGSI_FILE_TEMPORARY, tmp0); /* RCP t0.x, t0.x; */ tgsi_transform_op1_inst(ctx, TGSI_OPCODE_RCP, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_X, TGSI_FILE_TEMPORARY, tmp0); #endif /* SGT t0.y, t0.xxxx, tex.wwww; # bool b = d > 1 (NOTE tex.w == 1) */ tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_SGT, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_Y, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_X, TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_W); /* KILL_IF -tmp0.yyyy; # if -tmp0.y < 0, KILL */ tgsi_transform_kill_inst(ctx, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Y); /* compute coverage factor = (1-d)/(1-k) */ /* SUB t0.z, tex.w, tex.z; # m = 1 - k */ tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_Z, TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_W, TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_Z); /* RCP t0.z, t0.z; # t0.z = 1 / m */ newInst = tgsi_default_full_instruction(); newInst.Instruction.Opcode = TGSI_OPCODE_RCP; newInst.Instruction.NumDstRegs = 1; newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Dst[0].Register.Index = tmp0; newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Z; newInst.Instruction.NumSrcRegs = 1; newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY; newInst.Src[0].Register.Index = tmp0; newInst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_Z; ctx->emit_instruction(ctx, &newInst); /* SUB t0.y, 1, t0.x; # d = 1 - d */ tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_Y, TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_W, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_X); /* MUL t0.w, t0.y, t0.z; # coverage = d * m */ tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_W, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Y, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Z); /* SLE t0.y, t0.x, tex.z; # bool b = distance <= k */ tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_SLE, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_Y, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_X, TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_Z); /* CMP t0.w, -t0.y, tex.w, t0.w; * # if -t0.y < 0 then * t0.w = 1 * else * t0.w = t0.w */ tgsi_transform_op3_swz_inst(ctx, TGSI_OPCODE_CMP, TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_W, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Y, 1, TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_W, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_W); }