strlen(text),
&nvs->mesa.vp);
} else if (target == GL_FRAGMENT_PROGRAM_ARB) {
- _mesa_init_fragment_program(ctx, &nvs->mesa.fp, GL_VERTEX_PROGRAM_ARB, 0);
+ _mesa_init_fragment_program(ctx, &nvs->mesa.fp, GL_FRAGMENT_PROGRAM_ARB, 0);
_mesa_parse_arb_fragment_program(ctx,
GL_FRAGMENT_PROGRAM_ARB,
text,
NVS_TEX_TARGET_UNKNOWN = 0
} nvsTexTarget;
+typedef enum {
+ NVS_SCALE_1X = 0,
+ NVS_SCALE_2X = 1,
+ NVS_SCALE_4X = 2,
+ NVS_SCALE_8X = 3,
+ NVS_SCALE_INV_2X = 5,
+ NVS_SCALE_INV_4X = 6,
+ NVS_SCALE_INV_8X = 7,
+} nvsScale;
+
/* Arith/TEX instructions */
typedef struct nvs_instruction {
nvsFragmentHeader header;
nvsRegister dest;
unsigned int mask;
+ nvsScale dest_scale;
nvsRegister src[3];
void (*InitInstruction) (nvsFunc *);
int (*SupportsOpcode) (nvsFunc *, nvsOpcode);
+ int (*SupportsResultScale) (nvsFunc *, nvsScale);
void (*SetOpcode) (nvsFunc *, unsigned int opcode,
int slot);
void (*SetCCUpdate) (nvsFunc *);
nvsSwzComp *swizzle);
void (*SetResult) (nvsFunc *, nvsRegister *,
unsigned int mask, int slot);
+ void (*SetResultScale) (nvsFunc *, nvsScale);
void (*SetSource) (nvsFunc *, nvsRegister *, int pos);
void (*SetTexImageUnit) (nvsFunc *, int unit);
void (*SetSaturate) (nvsFunc *);
sif->saturate = saturate;
sif->dest = dst;
sif->mask = mask;
+ sif->dest_scale = NVS_SCALE_1X;
sif->src[0] = src0;
sif->src[1] = src1;
sif->src[2] = src2;
}
break;
case OPCODE_RSQ:
- if (rec->const_half.file != NVS_FILE_CONST) {
- GLfloat const_half[4] = { 0.5, 0.0, 0.0, 0.0 };
- pass0_make_reg(nvs, &rec->const_half, NVS_FILE_CONST,
- _mesa_add_unnamed_constant(
- nvs->mesa.vp.Base.Parameters,
- const_half, 4));
- COPY_4V(nvs->params[rec->const_half.index].val,
- const_half);
- }
pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1);
ARITHu(NVS_OP_LG2, temp, SMASK_X, 0,
nvsAbs(nvsSwizzle(src[0], X, X, X, X)),
nvr_unused, nvr_unused);
- ARITHu(NVS_OP_MUL, temp, SMASK_X, 0,
- nvsSwizzle(temp, X, X, X, X),
- nvsNegate(rec->const_half),
- nvr_unused);
+ nvsinst->dest_scale = NVS_SCALE_INV_2X;
ARITH (NVS_OP_EX2, dest, mask, sat,
- nvsSwizzle(temp, X, X, X, X),
+ nvsNegate(nvsSwizzle(temp, X, X, X, X)),
nvr_unused, nvr_unused);
break;
case OPCODE_SCS:
reg = pass2_mangle_reg(nvs, inst, inst->dest);
shader->SetResult(shader, ®, inst->mask, slot);
+
+ if (inst->dest_scale != NVS_SCALE_1X) {
+ shader->SetResultScale(shader, inst->dest_scale);
+ }
}
static int
* - These extend the NV30 routines, which are almost identical. NV40
* just has branching hacked into the instruction set.
*/
+static int
+NV40FPSupportsResultScale(nvsFunc *shader, nvsScale scale)
+{
+ switch (scale) {
+ case NVS_SCALE_1X:
+ case NVS_SCALE_2X:
+ case NVS_SCALE_4X:
+ case NVS_SCALE_8X:
+ case NVS_SCALE_INV_2X:
+ case NVS_SCALE_INV_4X:
+ case NVS_SCALE_INV_8X:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static void
+NV40FPSetResultScale(nvsFunc *shader, nvsScale scale)
+{
+ shader->inst[2] &= ~NV40_FP_OP_DST_SCALE_MASK;
+ shader->inst[2] |= ((unsigned int)scale << NV40_FP_OP_DST_SCALE_SHIFT);
+}
+
static void
NV40FPSetBranchTarget(nvsFunc *shader, int addr)
{
MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_REP , NVS_OP_REP , -1, -1, -1);
MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_RET , NVS_OP_RET , -1, -1, -1);
+ shader->SupportsResultScale = NV40FPSupportsResultScale;
+ shader->SetResultScale = NV40FPSetResultScale;
+
/* fragment.facing */
shader->GetSourceID = NV40FPGetSourceID;
/* high order bits of SRC1 */
#define NV40_FP_OP_OPCODE_IS_BRANCH (1<<31)
-#define NV40_FP_OP_SRC_SCALE_SHIFT 28
-#define NV40_FP_OP_SRC_SCALE_MASK (3 << 28)
+#define NV40_FP_OP_DST_SCALE_SHIFT 28
+#define NV40_FP_OP_DST_SCALE_MASK (3 << 28)
/* SRC1 LOOP */
#define NV40_FP_OP_LOOP_INCR_SHIFT 19