mirror of https://github.com/xemu-project/xemu.git
nv2a: Add custom mutable string object (QString is now immutable)
This commit is contained in:
parent
dc8eab47f6
commit
ee18e7bf35
|
@ -209,8 +209,8 @@ struct PixelShader {
|
|||
struct FCInputInfo final_input;
|
||||
int tex_modes[4], input_tex[4], dot_map[4];
|
||||
|
||||
QString *varE, *varF;
|
||||
QString *code;
|
||||
MString *varE, *varF;
|
||||
MString *code;
|
||||
int cur_stage;
|
||||
|
||||
int num_var_refs;
|
||||
|
@ -238,63 +238,63 @@ static void add_const_ref(struct PixelShader *ps, const char *var)
|
|||
}
|
||||
|
||||
// Get the code for a variable used in the program
|
||||
static QString* get_var(struct PixelShader *ps, int reg, bool is_dest)
|
||||
static MString* get_var(struct PixelShader *ps, int reg, bool is_dest)
|
||||
{
|
||||
switch (reg) {
|
||||
case PS_REGISTER_DISCARD:
|
||||
if (is_dest) {
|
||||
return qstring_from_str("");
|
||||
return mstring_from_str("");
|
||||
} else {
|
||||
return qstring_from_str("vec4(0.0)");
|
||||
return mstring_from_str("vec4(0.0)");
|
||||
}
|
||||
break;
|
||||
case PS_REGISTER_C0:
|
||||
if (ps->flags & PS_COMBINERCOUNT_UNIQUE_C0 || ps->cur_stage == 8) {
|
||||
QString *reg = qstring_from_fmt("c0_%d", ps->cur_stage);
|
||||
add_const_ref(ps, qstring_get_str(reg));
|
||||
MString *reg = mstring_from_fmt("c0_%d", ps->cur_stage);
|
||||
add_const_ref(ps, mstring_get_str(reg));
|
||||
return reg;
|
||||
} else { // Same c0
|
||||
add_const_ref(ps, "c0_0");
|
||||
return qstring_from_str("c0_0");
|
||||
return mstring_from_str("c0_0");
|
||||
}
|
||||
break;
|
||||
case PS_REGISTER_C1:
|
||||
if (ps->flags & PS_COMBINERCOUNT_UNIQUE_C1 || ps->cur_stage == 8) {
|
||||
QString *reg = qstring_from_fmt("c1_%d", ps->cur_stage);
|
||||
add_const_ref(ps, qstring_get_str(reg));
|
||||
MString *reg = mstring_from_fmt("c1_%d", ps->cur_stage);
|
||||
add_const_ref(ps, mstring_get_str(reg));
|
||||
return reg;
|
||||
} else { // Same c1
|
||||
add_const_ref(ps, "c1_0");
|
||||
return qstring_from_str("c1_0");
|
||||
return mstring_from_str("c1_0");
|
||||
}
|
||||
break;
|
||||
case PS_REGISTER_FOG:
|
||||
return qstring_from_str("pFog");
|
||||
return mstring_from_str("pFog");
|
||||
case PS_REGISTER_V0:
|
||||
return qstring_from_str("v0");
|
||||
return mstring_from_str("v0");
|
||||
case PS_REGISTER_V1:
|
||||
return qstring_from_str("v1");
|
||||
return mstring_from_str("v1");
|
||||
case PS_REGISTER_T0:
|
||||
return qstring_from_str("t0");
|
||||
return mstring_from_str("t0");
|
||||
case PS_REGISTER_T1:
|
||||
return qstring_from_str("t1");
|
||||
return mstring_from_str("t1");
|
||||
case PS_REGISTER_T2:
|
||||
return qstring_from_str("t2");
|
||||
return mstring_from_str("t2");
|
||||
case PS_REGISTER_T3:
|
||||
return qstring_from_str("t3");
|
||||
return mstring_from_str("t3");
|
||||
case PS_REGISTER_R0:
|
||||
add_var_ref(ps, "r0");
|
||||
return qstring_from_str("r0");
|
||||
return mstring_from_str("r0");
|
||||
case PS_REGISTER_R1:
|
||||
add_var_ref(ps, "r1");
|
||||
return qstring_from_str("r1");
|
||||
return mstring_from_str("r1");
|
||||
case PS_REGISTER_V1R0_SUM:
|
||||
add_var_ref(ps, "r0");
|
||||
return qstring_from_str("vec4(v1.rgb + r0.rgb, 0.0)");
|
||||
return mstring_from_str("vec4(v1.rgb + r0.rgb, 0.0)");
|
||||
case PS_REGISTER_EF_PROD:
|
||||
return qstring_from_fmt("vec4(%s * %s, 0.0)",
|
||||
qstring_get_str(ps->varE),
|
||||
qstring_get_str(ps->varF));
|
||||
return mstring_from_fmt("vec4(%s * %s, 0.0)",
|
||||
mstring_get_str(ps->varE),
|
||||
mstring_get_str(ps->varF));
|
||||
default:
|
||||
assert(false);
|
||||
return NULL;
|
||||
|
@ -302,17 +302,17 @@ static QString* get_var(struct PixelShader *ps, int reg, bool is_dest)
|
|||
}
|
||||
|
||||
// Get input variable code
|
||||
static QString* get_input_var(struct PixelShader *ps, struct InputInfo in, bool is_alpha)
|
||||
static MString* get_input_var(struct PixelShader *ps, struct InputInfo in, bool is_alpha)
|
||||
{
|
||||
QString *reg = get_var(ps, in.reg, false);
|
||||
MString *reg = get_var(ps, in.reg, false);
|
||||
|
||||
if (!is_alpha) {
|
||||
switch (in.chan) {
|
||||
case PS_CHANNEL_RGB:
|
||||
qstring_append(reg, ".rgb");
|
||||
mstring_append(reg, ".rgb");
|
||||
break;
|
||||
case PS_CHANNEL_ALPHA:
|
||||
qstring_append(reg, ".aaa");
|
||||
mstring_append(reg, ".aaa");
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
|
@ -321,10 +321,10 @@ static QString* get_input_var(struct PixelShader *ps, struct InputInfo in, bool
|
|||
} else {
|
||||
switch (in.chan) {
|
||||
case PS_CHANNEL_BLUE:
|
||||
qstring_append(reg, ".b");
|
||||
mstring_append(reg, ".b");
|
||||
break;
|
||||
case PS_CHANNEL_ALPHA:
|
||||
qstring_append(reg, ".a");
|
||||
mstring_append(reg, ".a");
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
|
@ -332,65 +332,65 @@ static QString* get_input_var(struct PixelShader *ps, struct InputInfo in, bool
|
|||
}
|
||||
}
|
||||
|
||||
QString *res;
|
||||
MString *res;
|
||||
switch (in.mod) {
|
||||
case PS_INPUTMAPPING_UNSIGNED_IDENTITY:
|
||||
res = qstring_from_fmt("max(%s, 0.0)", qstring_get_str(reg));
|
||||
res = mstring_from_fmt("max(%s, 0.0)", mstring_get_str(reg));
|
||||
break;
|
||||
case PS_INPUTMAPPING_UNSIGNED_INVERT:
|
||||
res = qstring_from_fmt("(1.0 - clamp(%s, 0.0, 1.0))", qstring_get_str(reg));
|
||||
res = mstring_from_fmt("(1.0 - clamp(%s, 0.0, 1.0))", mstring_get_str(reg));
|
||||
break;
|
||||
case PS_INPUTMAPPING_EXPAND_NORMAL:
|
||||
res = qstring_from_fmt("(2.0 * max(%s, 0.0) - 1.0)", qstring_get_str(reg));
|
||||
res = mstring_from_fmt("(2.0 * max(%s, 0.0) - 1.0)", mstring_get_str(reg));
|
||||
break;
|
||||
case PS_INPUTMAPPING_EXPAND_NEGATE:
|
||||
res = qstring_from_fmt("(-2.0 * max(%s, 0.0) + 1.0)", qstring_get_str(reg));
|
||||
res = mstring_from_fmt("(-2.0 * max(%s, 0.0) + 1.0)", mstring_get_str(reg));
|
||||
break;
|
||||
case PS_INPUTMAPPING_HALFBIAS_NORMAL:
|
||||
res = qstring_from_fmt("(max(%s, 0.0) - 0.5)", qstring_get_str(reg));
|
||||
res = mstring_from_fmt("(max(%s, 0.0) - 0.5)", mstring_get_str(reg));
|
||||
break;
|
||||
case PS_INPUTMAPPING_HALFBIAS_NEGATE:
|
||||
res = qstring_from_fmt("(-max(%s, 0.0) + 0.5)", qstring_get_str(reg));
|
||||
res = mstring_from_fmt("(-max(%s, 0.0) + 0.5)", mstring_get_str(reg));
|
||||
break;
|
||||
case PS_INPUTMAPPING_SIGNED_IDENTITY:
|
||||
qobject_ref(reg);
|
||||
mstring_ref(reg);
|
||||
res = reg;
|
||||
break;
|
||||
case PS_INPUTMAPPING_SIGNED_NEGATE:
|
||||
res = qstring_from_fmt("-%s", qstring_get_str(reg));
|
||||
res = mstring_from_fmt("-%s", mstring_get_str(reg));
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
qobject_unref(reg);
|
||||
mstring_unref(reg);
|
||||
return res;
|
||||
}
|
||||
|
||||
// Get code for the output mapping of a stage
|
||||
static QString* get_output(QString *reg, int mapping)
|
||||
static MString* get_output(MString *reg, int mapping)
|
||||
{
|
||||
QString *res;
|
||||
MString *res;
|
||||
switch (mapping) {
|
||||
case PS_COMBINEROUTPUT_IDENTITY:
|
||||
qobject_ref(reg);
|
||||
mstring_ref(reg);
|
||||
res = reg;
|
||||
break;
|
||||
case PS_COMBINEROUTPUT_BIAS:
|
||||
res = qstring_from_fmt("(%s - 0.5)", qstring_get_str(reg));
|
||||
res = mstring_from_fmt("(%s - 0.5)", mstring_get_str(reg));
|
||||
break;
|
||||
case PS_COMBINEROUTPUT_SHIFTLEFT_1:
|
||||
res = qstring_from_fmt("(%s * 2.0)", qstring_get_str(reg));
|
||||
res = mstring_from_fmt("(%s * 2.0)", mstring_get_str(reg));
|
||||
break;
|
||||
case PS_COMBINEROUTPUT_SHIFTLEFT_1_BIAS:
|
||||
res = qstring_from_fmt("((%s - 0.5) * 2.0)", qstring_get_str(reg));
|
||||
res = mstring_from_fmt("((%s - 0.5) * 2.0)", mstring_get_str(reg));
|
||||
break;
|
||||
case PS_COMBINEROUTPUT_SHIFTLEFT_2:
|
||||
res = qstring_from_fmt("(%s * 4.0)", qstring_get_str(reg));
|
||||
res = mstring_from_fmt("(%s * 4.0)", mstring_get_str(reg));
|
||||
break;
|
||||
case PS_COMBINEROUTPUT_SHIFTRIGHT_1:
|
||||
res = qstring_from_fmt("(%s / 2.0)", qstring_get_str(reg));
|
||||
res = mstring_from_fmt("(%s / 2.0)", mstring_get_str(reg));
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
|
@ -404,94 +404,94 @@ static void add_stage_code(struct PixelShader *ps,
|
|||
struct InputVarInfo input, struct OutputInfo output,
|
||||
const char *write_mask, bool is_alpha)
|
||||
{
|
||||
QString *a = get_input_var(ps, input.a, is_alpha);
|
||||
QString *b = get_input_var(ps, input.b, is_alpha);
|
||||
QString *c = get_input_var(ps, input.c, is_alpha);
|
||||
QString *d = get_input_var(ps, input.d, is_alpha);
|
||||
MString *a = get_input_var(ps, input.a, is_alpha);
|
||||
MString *b = get_input_var(ps, input.b, is_alpha);
|
||||
MString *c = get_input_var(ps, input.c, is_alpha);
|
||||
MString *d = get_input_var(ps, input.d, is_alpha);
|
||||
|
||||
const char *caster = "";
|
||||
if (strlen(write_mask) == 3) {
|
||||
caster = "vec3";
|
||||
}
|
||||
|
||||
QString *ab;
|
||||
MString *ab;
|
||||
if (output.ab_op == PS_COMBINEROUTPUT_AB_DOT_PRODUCT) {
|
||||
ab = qstring_from_fmt("dot(%s, %s)",
|
||||
qstring_get_str(a), qstring_get_str(b));
|
||||
ab = mstring_from_fmt("dot(%s, %s)",
|
||||
mstring_get_str(a), mstring_get_str(b));
|
||||
} else {
|
||||
ab = qstring_from_fmt("(%s * %s)",
|
||||
qstring_get_str(a), qstring_get_str(b));
|
||||
ab = mstring_from_fmt("(%s * %s)",
|
||||
mstring_get_str(a), mstring_get_str(b));
|
||||
}
|
||||
|
||||
QString *cd;
|
||||
MString *cd;
|
||||
if (output.cd_op == PS_COMBINEROUTPUT_CD_DOT_PRODUCT) {
|
||||
cd = qstring_from_fmt("dot(%s, %s)",
|
||||
qstring_get_str(c), qstring_get_str(d));
|
||||
cd = mstring_from_fmt("dot(%s, %s)",
|
||||
mstring_get_str(c), mstring_get_str(d));
|
||||
} else {
|
||||
cd = qstring_from_fmt("(%s * %s)",
|
||||
qstring_get_str(c), qstring_get_str(d));
|
||||
cd = mstring_from_fmt("(%s * %s)",
|
||||
mstring_get_str(c), mstring_get_str(d));
|
||||
}
|
||||
|
||||
QString *ab_mapping = get_output(ab, output.mapping);
|
||||
QString *cd_mapping = get_output(cd, output.mapping);
|
||||
QString *ab_dest = get_var(ps, output.ab, true);
|
||||
QString *cd_dest = get_var(ps, output.cd, true);
|
||||
QString *sum_dest = get_var(ps, output.muxsum, true);
|
||||
MString *ab_mapping = get_output(ab, output.mapping);
|
||||
MString *cd_mapping = get_output(cd, output.mapping);
|
||||
MString *ab_dest = get_var(ps, output.ab, true);
|
||||
MString *cd_dest = get_var(ps, output.cd, true);
|
||||
MString *sum_dest = get_var(ps, output.muxsum, true);
|
||||
|
||||
if (qstring_get_length(ab_dest)) {
|
||||
qstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n",
|
||||
qstring_get_str(ab_dest), write_mask, caster, qstring_get_str(ab_mapping));
|
||||
if (mstring_get_length(ab_dest)) {
|
||||
mstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n",
|
||||
mstring_get_str(ab_dest), write_mask, caster, mstring_get_str(ab_mapping));
|
||||
} else {
|
||||
qobject_unref(ab_dest);
|
||||
qobject_ref(ab_mapping);
|
||||
mstring_unref(ab_dest);
|
||||
mstring_ref(ab_mapping);
|
||||
ab_dest = ab_mapping;
|
||||
}
|
||||
|
||||
if (qstring_get_length(cd_dest)) {
|
||||
qstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n",
|
||||
qstring_get_str(cd_dest), write_mask, caster, qstring_get_str(cd_mapping));
|
||||
if (mstring_get_length(cd_dest)) {
|
||||
mstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n",
|
||||
mstring_get_str(cd_dest), write_mask, caster, mstring_get_str(cd_mapping));
|
||||
} else {
|
||||
qobject_unref(cd_dest);
|
||||
qobject_ref(cd_mapping);
|
||||
mstring_unref(cd_dest);
|
||||
mstring_ref(cd_mapping);
|
||||
cd_dest = cd_mapping;
|
||||
}
|
||||
|
||||
if (!is_alpha && output.flags & PS_COMBINEROUTPUT_AB_BLUE_TO_ALPHA) {
|
||||
qstring_append_fmt(ps->code, "%s.a = %s.b;\n",
|
||||
qstring_get_str(ab_dest), qstring_get_str(ab_dest));
|
||||
mstring_append_fmt(ps->code, "%s.a = %s.b;\n",
|
||||
mstring_get_str(ab_dest), mstring_get_str(ab_dest));
|
||||
}
|
||||
if (!is_alpha && output.flags & PS_COMBINEROUTPUT_CD_BLUE_TO_ALPHA) {
|
||||
qstring_append_fmt(ps->code, "%s.a = %s.b;\n",
|
||||
qstring_get_str(cd_dest), qstring_get_str(cd_dest));
|
||||
mstring_append_fmt(ps->code, "%s.a = %s.b;\n",
|
||||
mstring_get_str(cd_dest), mstring_get_str(cd_dest));
|
||||
}
|
||||
|
||||
QString *sum;
|
||||
MString *sum;
|
||||
if (output.muxsum_op == PS_COMBINEROUTPUT_AB_CD_SUM) {
|
||||
sum = qstring_from_fmt("(%s + %s)", qstring_get_str(ab), qstring_get_str(cd));
|
||||
sum = mstring_from_fmt("(%s + %s)", mstring_get_str(ab), mstring_get_str(cd));
|
||||
} else {
|
||||
sum = qstring_from_fmt("((r0.a >= 0.5) ? %s(%s) : %s(%s))",
|
||||
caster, qstring_get_str(cd), caster, qstring_get_str(ab));
|
||||
sum = mstring_from_fmt("((r0.a >= 0.5) ? %s(%s) : %s(%s))",
|
||||
caster, mstring_get_str(cd), caster, mstring_get_str(ab));
|
||||
}
|
||||
|
||||
QString *sum_mapping = get_output(sum, output.mapping);
|
||||
if (qstring_get_length(sum_dest)) {
|
||||
qstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n",
|
||||
qstring_get_str(sum_dest), write_mask, caster, qstring_get_str(sum_mapping));
|
||||
MString *sum_mapping = get_output(sum, output.mapping);
|
||||
if (mstring_get_length(sum_dest)) {
|
||||
mstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n",
|
||||
mstring_get_str(sum_dest), write_mask, caster, mstring_get_str(sum_mapping));
|
||||
}
|
||||
|
||||
qobject_unref(a);
|
||||
qobject_unref(b);
|
||||
qobject_unref(c);
|
||||
qobject_unref(d);
|
||||
qobject_unref(ab);
|
||||
qobject_unref(cd);
|
||||
qobject_unref(ab_mapping);
|
||||
qobject_unref(cd_mapping);
|
||||
qobject_unref(ab_dest);
|
||||
qobject_unref(cd_dest);
|
||||
qobject_unref(sum_dest);
|
||||
qobject_unref(sum);
|
||||
qobject_unref(sum_mapping);
|
||||
mstring_unref(a);
|
||||
mstring_unref(b);
|
||||
mstring_unref(c);
|
||||
mstring_unref(d);
|
||||
mstring_unref(ab);
|
||||
mstring_unref(cd);
|
||||
mstring_unref(ab_mapping);
|
||||
mstring_unref(cd_mapping);
|
||||
mstring_unref(ab_dest);
|
||||
mstring_unref(cd_dest);
|
||||
mstring_unref(sum_dest);
|
||||
mstring_unref(sum);
|
||||
mstring_unref(sum_mapping);
|
||||
}
|
||||
|
||||
// Add code for the final combiner stage
|
||||
|
@ -500,40 +500,40 @@ static void add_final_stage_code(struct PixelShader *ps, struct FCInputInfo fina
|
|||
ps->varE = get_input_var(ps, final.e, false);
|
||||
ps->varF = get_input_var(ps, final.f, false);
|
||||
|
||||
QString *a = get_input_var(ps, final.a, false);
|
||||
QString *b = get_input_var(ps, final.b, false);
|
||||
QString *c = get_input_var(ps, final.c, false);
|
||||
QString *d = get_input_var(ps, final.d, false);
|
||||
QString *g = get_input_var(ps, final.g, true);
|
||||
MString *a = get_input_var(ps, final.a, false);
|
||||
MString *b = get_input_var(ps, final.b, false);
|
||||
MString *c = get_input_var(ps, final.c, false);
|
||||
MString *d = get_input_var(ps, final.d, false);
|
||||
MString *g = get_input_var(ps, final.g, true);
|
||||
|
||||
qstring_append_fmt(ps->code, "fragColor.rgb = %s + mix(vec3(%s), vec3(%s), vec3(%s));\n",
|
||||
qstring_get_str(d), qstring_get_str(c),
|
||||
qstring_get_str(b), qstring_get_str(a));
|
||||
qstring_append_fmt(ps->code, "fragColor.a = %s;\n", qstring_get_str(g));
|
||||
mstring_append_fmt(ps->code, "fragColor.rgb = %s + mix(vec3(%s), vec3(%s), vec3(%s));\n",
|
||||
mstring_get_str(d), mstring_get_str(c),
|
||||
mstring_get_str(b), mstring_get_str(a));
|
||||
mstring_append_fmt(ps->code, "fragColor.a = %s;\n", mstring_get_str(g));
|
||||
|
||||
qobject_unref(a);
|
||||
qobject_unref(b);
|
||||
qobject_unref(c);
|
||||
qobject_unref(d);
|
||||
qobject_unref(g);
|
||||
mstring_unref(a);
|
||||
mstring_unref(b);
|
||||
mstring_unref(c);
|
||||
mstring_unref(d);
|
||||
mstring_unref(g);
|
||||
|
||||
qobject_unref(ps->varE);
|
||||
qobject_unref(ps->varF);
|
||||
mstring_unref(ps->varE);
|
||||
mstring_unref(ps->varF);
|
||||
ps->varE = ps->varF = NULL;
|
||||
}
|
||||
|
||||
static QString* psh_convert(struct PixelShader *ps)
|
||||
static MString* psh_convert(struct PixelShader *ps)
|
||||
{
|
||||
int i;
|
||||
|
||||
QString *preflight = qstring_new();
|
||||
qstring_append(preflight, STRUCT_VERTEX_DATA);
|
||||
qstring_append(preflight, "noperspective in VertexData g_vtx;\n");
|
||||
qstring_append(preflight, "#define vtx g_vtx\n");
|
||||
qstring_append(preflight, "\n");
|
||||
qstring_append(preflight, "out vec4 fragColor;\n");
|
||||
qstring_append(preflight, "\n");
|
||||
qstring_append(preflight, "uniform vec4 fogColor;\n");
|
||||
MString *preflight = mstring_new();
|
||||
mstring_append(preflight, STRUCT_VERTEX_DATA);
|
||||
mstring_append(preflight, "noperspective in VertexData g_vtx;\n");
|
||||
mstring_append(preflight, "#define vtx g_vtx\n");
|
||||
mstring_append(preflight, "\n");
|
||||
mstring_append(preflight, "out vec4 fragColor;\n");
|
||||
mstring_append(preflight, "\n");
|
||||
mstring_append(preflight, "uniform vec4 fogColor;\n");
|
||||
|
||||
const char *dotmap_funcs[] = {
|
||||
"dotmap_zero_to_one",
|
||||
|
@ -546,7 +546,7 @@ static QString* psh_convert(struct PixelShader *ps)
|
|||
"dotmap_hilo_hemisphere",
|
||||
};
|
||||
|
||||
qstring_append_fmt(preflight,
|
||||
mstring_append_fmt(preflight,
|
||||
"float sign1(float x) {\n"
|
||||
" x *= 255.0;\n"
|
||||
" return (x-128.0)/127.0;\n"
|
||||
|
@ -608,57 +608,57 @@ static QString* psh_convert(struct PixelShader *ps)
|
|||
);
|
||||
|
||||
/* Window Clipping */
|
||||
QString *clip = qstring_new();
|
||||
MString *clip = mstring_new();
|
||||
if (ps->state.window_clip_count != 0) {
|
||||
qstring_append_fmt(preflight, "uniform ivec4 clipRegion[%d];\n",
|
||||
mstring_append_fmt(preflight, "uniform ivec4 clipRegion[%d];\n",
|
||||
ps->state.window_clip_count);
|
||||
qstring_append_fmt(clip, "/* Window-clip (%s) */\n",
|
||||
mstring_append_fmt(clip, "/* Window-clip (%s) */\n",
|
||||
ps->state.window_clip_exclusive ?
|
||||
"Exclusive" : "Inclusive");
|
||||
if (!ps->state.window_clip_exclusive) {
|
||||
qstring_append(clip, "bool clipContained = false;\n");
|
||||
mstring_append(clip, "bool clipContained = false;\n");
|
||||
}
|
||||
qstring_append_fmt(clip, "for (int i = 0; i < %d; i++) {\n",
|
||||
mstring_append_fmt(clip, "for (int i = 0; i < %d; i++) {\n",
|
||||
ps->state.window_clip_count);
|
||||
qstring_append(clip, " bvec4 clipTest = bvec4(lessThan(gl_FragCoord.xy, clipRegion[i].xy),\n"
|
||||
mstring_append(clip, " bvec4 clipTest = bvec4(lessThan(gl_FragCoord.xy, clipRegion[i].xy),\n"
|
||||
" greaterThan(gl_FragCoord.xy, clipRegion[i].zw));\n"
|
||||
" if (!any(clipTest)) {\n");
|
||||
if (ps->state.window_clip_exclusive) {
|
||||
/* Pixel in clip region = exclude by discarding */
|
||||
qstring_append(clip, " discard;\n");
|
||||
mstring_append(clip, " discard;\n");
|
||||
assert(false); /* Untested */
|
||||
} else {
|
||||
/* Pixel in clip region = mark pixel as contained and leave */
|
||||
qstring_append(clip, " clipContained = true;\n"
|
||||
mstring_append(clip, " clipContained = true;\n"
|
||||
" break;\n");
|
||||
}
|
||||
qstring_append(clip, " }\n"
|
||||
mstring_append(clip, " }\n"
|
||||
"}\n");
|
||||
/* Check for inclusive window clip */
|
||||
if (!ps->state.window_clip_exclusive) {
|
||||
qstring_append(clip, "if (!clipContained) { discard; }\n");
|
||||
mstring_append(clip, "if (!clipContained) { discard; }\n");
|
||||
}
|
||||
} else if (ps->state.window_clip_exclusive) {
|
||||
/* Clip everything */
|
||||
qstring_append(clip, "discard;\n");
|
||||
mstring_append(clip, "discard;\n");
|
||||
}
|
||||
|
||||
/* calculate perspective-correct inputs */
|
||||
QString *vars = qstring_new();
|
||||
qstring_append(vars, "vec4 pD0 = vtx.D0 / vtx.inv_w;\n");
|
||||
qstring_append(vars, "vec4 pD1 = vtx.D1 / vtx.inv_w;\n");
|
||||
qstring_append(vars, "vec4 pB0 = vtx.B0 / vtx.inv_w;\n");
|
||||
qstring_append(vars, "vec4 pB1 = vtx.B1 / vtx.inv_w;\n");
|
||||
qstring_append(vars, "vec4 pFog = vec4(fogColor.rgb, clamp(vtx.Fog / vtx.inv_w, 0.0, 1.0));\n");
|
||||
qstring_append(vars, "vec4 pT0 = vtx.T0 / vtx.inv_w;\n");
|
||||
qstring_append(vars, "vec4 pT1 = vtx.T1 / vtx.inv_w;\n");
|
||||
qstring_append(vars, "vec4 pT2 = vtx.T2 / vtx.inv_w;\n");
|
||||
qstring_append(vars, "vec4 pT3 = vtx.T3 / vtx.inv_w;\n");
|
||||
qstring_append(vars, "\n");
|
||||
qstring_append(vars, "vec4 v0 = pD0;\n");
|
||||
qstring_append(vars, "vec4 v1 = pD1;\n");
|
||||
MString *vars = mstring_new();
|
||||
mstring_append(vars, "vec4 pD0 = vtx.D0 / vtx.inv_w;\n");
|
||||
mstring_append(vars, "vec4 pD1 = vtx.D1 / vtx.inv_w;\n");
|
||||
mstring_append(vars, "vec4 pB0 = vtx.B0 / vtx.inv_w;\n");
|
||||
mstring_append(vars, "vec4 pB1 = vtx.B1 / vtx.inv_w;\n");
|
||||
mstring_append(vars, "vec4 pFog = vec4(fogColor.rgb, clamp(vtx.Fog / vtx.inv_w, 0.0, 1.0));\n");
|
||||
mstring_append(vars, "vec4 pT0 = vtx.T0 / vtx.inv_w;\n");
|
||||
mstring_append(vars, "vec4 pT1 = vtx.T1 / vtx.inv_w;\n");
|
||||
mstring_append(vars, "vec4 pT2 = vtx.T2 / vtx.inv_w;\n");
|
||||
mstring_append(vars, "vec4 pT3 = vtx.T3 / vtx.inv_w;\n");
|
||||
mstring_append(vars, "\n");
|
||||
mstring_append(vars, "vec4 v0 = pD0;\n");
|
||||
mstring_append(vars, "vec4 v1 = pD1;\n");
|
||||
|
||||
ps->code = qstring_new();
|
||||
ps->code = mstring_new();
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
||||
|
@ -672,7 +672,7 @@ static QString* psh_convert(struct PixelShader *ps)
|
|||
|
||||
switch (ps->tex_modes[i]) {
|
||||
case PS_TEXTUREMODES_NONE:
|
||||
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_NONE */\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_NONE */\n",
|
||||
i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_PROJECT2D: {
|
||||
|
@ -690,29 +690,29 @@ static QString* psh_convert(struct PixelShader *ps)
|
|||
NV2A_UNIMPLEMENTED("Convolution for 2D textures");
|
||||
}
|
||||
}
|
||||
qstring_append_fmt(vars, "vec4 t%d = %s(texSamp%d, pT%d.xyw);\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = %s(texSamp%d, pT%d.xyw);\n",
|
||||
i, lookup, i, i);
|
||||
break;
|
||||
}
|
||||
case PS_TEXTUREMODES_PROJECT3D:
|
||||
sampler_type = "sampler3D";
|
||||
qstring_append_fmt(vars, "vec4 t%d = textureProj(texSamp%d, pT%d.xyzw);\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = textureProj(texSamp%d, pT%d.xyzw);\n",
|
||||
i, i, i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_CUBEMAP:
|
||||
sampler_type = "samplerCube";
|
||||
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xyz / pT%d.w);\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xyz / pT%d.w);\n",
|
||||
i, i, i, i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_PASSTHRU:
|
||||
qstring_append_fmt(vars, "vec4 t%d = pT%d;\n", i, i);
|
||||
mstring_append_fmt(vars, "vec4 t%d = pT%d;\n", i, i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_CLIPPLANE: {
|
||||
int j;
|
||||
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_CLIPPLANE */\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_CLIPPLANE */\n",
|
||||
i);
|
||||
for (j = 0; j < 4; j++) {
|
||||
qstring_append_fmt(vars, " if(pT%d.%c %s 0.0) { discard; };\n",
|
||||
mstring_append_fmt(vars, " if(pT%d.%c %s 0.0) { discard; };\n",
|
||||
i, "xyzw"[j],
|
||||
ps->state.compare_mode[i][j] ? ">=" : "<");
|
||||
}
|
||||
|
@ -721,143 +721,143 @@ static QString* psh_convert(struct PixelShader *ps)
|
|||
case PS_TEXTUREMODES_BUMPENVMAP:
|
||||
assert(i >= 1);
|
||||
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
|
||||
qstring_append_fmt(preflight, "uniform mat2 bumpMat%d;\n", i);
|
||||
mstring_append_fmt(preflight, "uniform mat2 bumpMat%d;\n", i);
|
||||
|
||||
if (ps->state.snorm_tex[ps->input_tex[i]]) {
|
||||
/* Input color channels already signed (FIXME: May not always want signed textures in this case) */
|
||||
qstring_append_fmt(vars, "vec2 dsdt%d = t%d.bg;\n",
|
||||
mstring_append_fmt(vars, "vec2 dsdt%d = t%d.bg;\n",
|
||||
i, ps->input_tex[i]);
|
||||
} else {
|
||||
/* Convert to signed (FIXME: loss of accuracy due to filtering/interpolation) */
|
||||
qstring_append_fmt(vars, "vec2 dsdt%d = vec2(sign3(t%d.b), sign3(t%d.g));\n",
|
||||
mstring_append_fmt(vars, "vec2 dsdt%d = vec2(sign3(t%d.b), sign3(t%d.g));\n",
|
||||
i, ps->input_tex[i], ps->input_tex[i]);
|
||||
}
|
||||
|
||||
/* FIXME: Do bumpMat swizzle on CPU before upload */
|
||||
qstring_append_fmt(vars, "dsdt%d = mat2(bumpMat%d[0].xy, bumpMat%d[1].yx) * dsdt%d;\n",
|
||||
mstring_append_fmt(vars, "dsdt%d = mat2(bumpMat%d[0].xy, bumpMat%d[1].yx) * dsdt%d;\n",
|
||||
i, i, i, i);
|
||||
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xy + dsdt%d);\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xy + dsdt%d);\n",
|
||||
i, i, i, i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_BUMPENVMAP_LUM:
|
||||
assert(i >= 1);
|
||||
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
|
||||
qstring_append_fmt(preflight, "uniform float bumpScale%d;\n", i);
|
||||
qstring_append_fmt(preflight, "uniform float bumpOffset%d;\n", i);
|
||||
qstring_append_fmt(preflight, "uniform mat2 bumpMat%d;\n", i);
|
||||
mstring_append_fmt(preflight, "uniform float bumpScale%d;\n", i);
|
||||
mstring_append_fmt(preflight, "uniform float bumpOffset%d;\n", i);
|
||||
mstring_append_fmt(preflight, "uniform mat2 bumpMat%d;\n", i);
|
||||
|
||||
if (ps->state.snorm_tex[ps->input_tex[i]]) {
|
||||
/* Input color channels already signed (FIXME: May not always want signed textures in this case) */
|
||||
qstring_append_fmt(vars, "vec3 dsdtl%d = vec3(t%d.bg, sign3_to_0_to_1(t%d.r));\n",
|
||||
mstring_append_fmt(vars, "vec3 dsdtl%d = vec3(t%d.bg, sign3_to_0_to_1(t%d.r));\n",
|
||||
i, ps->input_tex[i], ps->input_tex[i]);
|
||||
} else {
|
||||
/* Convert to signed (FIXME: loss of accuracy due to filtering/interpolation) */
|
||||
qstring_append_fmt(vars, "vec3 dsdtl%d = vec3(sign3(t%d.b), sign3(t%d.g), t%d.r);\n",
|
||||
mstring_append_fmt(vars, "vec3 dsdtl%d = vec3(sign3(t%d.b), sign3(t%d.g), t%d.r);\n",
|
||||
i, ps->input_tex[i], ps->input_tex[i], ps->input_tex[i]);
|
||||
}
|
||||
|
||||
/* FIXME: Do bumpMat swizzle on CPU before upload */
|
||||
qstring_append_fmt(vars, "dsdtl%d.st = mat2(bumpMat%d[0].xy, bumpMat%d[1].yx) * dsdtl%d.st;\n",
|
||||
mstring_append_fmt(vars, "dsdtl%d.st = mat2(bumpMat%d[0].xy, bumpMat%d[1].yx) * dsdtl%d.st;\n",
|
||||
i, i, i, i);
|
||||
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xy + dsdtl%d.st);\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xy + dsdtl%d.st);\n",
|
||||
i, i, i, i);
|
||||
qstring_append_fmt(vars, "t%d = t%d * (bumpScale%d * dsdtl%d.p + bumpOffset%d);\n",
|
||||
mstring_append_fmt(vars, "t%d = t%d * (bumpScale%d * dsdtl%d.p + bumpOffset%d);\n",
|
||||
i, i, i, i, i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_BRDF:
|
||||
assert(i >= 2);
|
||||
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_BRDF */\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_BRDF */\n",
|
||||
i);
|
||||
NV2A_UNIMPLEMENTED("PS_TEXTUREMODES_BRDF");
|
||||
break;
|
||||
case PS_TEXTUREMODES_DOT_ST:
|
||||
assert(i >= 2);
|
||||
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
|
||||
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_ST */\n");
|
||||
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_ST */\n");
|
||||
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i, dotmap_func, ps->input_tex[i]);
|
||||
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, vec2(dot%d, dot%d));\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, vec2(dot%d, dot%d));\n",
|
||||
i, i, i-1, i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_DOT_ZW:
|
||||
assert(i >= 2);
|
||||
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_ZW */\n");
|
||||
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_ZW */\n");
|
||||
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i, dotmap_func, ps->input_tex[i]);
|
||||
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0);\n", i);
|
||||
// FIXME: qstring_append_fmt(vars, "gl_FragDepth = t%d.x;\n", i);
|
||||
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0);\n", i);
|
||||
// FIXME: mstring_append_fmt(vars, "gl_FragDepth = t%d.x;\n", i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_DOT_RFLCT_DIFF:
|
||||
assert(i == 2);
|
||||
sampler_type = "samplerCube";
|
||||
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_RFLCT_DIFF */\n");
|
||||
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_RFLCT_DIFF */\n");
|
||||
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i, dotmap_func, ps->input_tex[i]);
|
||||
assert(ps->dot_map[i+1] < 8);
|
||||
qstring_append_fmt(vars, "float dot%d_n = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
mstring_append_fmt(vars, "float dot%d_n = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i+1, dotmap_funcs[ps->dot_map[i+1]], ps->input_tex[i+1]);
|
||||
qstring_append_fmt(vars, "vec3 n_%d = vec3(dot%d, dot%d, dot%d_n);\n",
|
||||
mstring_append_fmt(vars, "vec3 n_%d = vec3(dot%d, dot%d, dot%d_n);\n",
|
||||
i, i-1, i, i);
|
||||
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, n_%d);\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, n_%d);\n",
|
||||
i, i, i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_DOT_RFLCT_SPEC:
|
||||
assert(i == 3);
|
||||
sampler_type = "samplerCube";
|
||||
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_RFLCT_SPEC */\n");
|
||||
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_RFLCT_SPEC */\n");
|
||||
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i, dotmap_func, ps->input_tex[i]);
|
||||
qstring_append_fmt(vars, "vec3 n_%d = vec3(dot%d, dot%d, dot%d);\n",
|
||||
mstring_append_fmt(vars, "vec3 n_%d = vec3(dot%d, dot%d, dot%d);\n",
|
||||
i, i-2, i-1, i);
|
||||
qstring_append_fmt(vars, "vec3 e_%d = vec3(pT%d.w, pT%d.w, pT%d.w);\n",
|
||||
mstring_append_fmt(vars, "vec3 e_%d = vec3(pT%d.w, pT%d.w, pT%d.w);\n",
|
||||
i, i-2, i-1, i);
|
||||
qstring_append_fmt(vars, "vec3 rv_%d = 2*n_%d*dot(n_%d,e_%d)/dot(n_%d,n_%d) - e_%d;\n",
|
||||
mstring_append_fmt(vars, "vec3 rv_%d = 2*n_%d*dot(n_%d,e_%d)/dot(n_%d,n_%d) - e_%d;\n",
|
||||
i, i, i, i, i, i, i);
|
||||
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, rv_%d);\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, rv_%d);\n",
|
||||
i, i, i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_DOT_STR_3D:
|
||||
assert(i == 3);
|
||||
sampler_type = "sampler3D";
|
||||
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_STR_3D */\n");
|
||||
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_STR_3D */\n");
|
||||
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i, dotmap_func, ps->input_tex[i]);
|
||||
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, vec3(dot%d, dot%d, dot%d));\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, vec3(dot%d, dot%d, dot%d));\n",
|
||||
i, i, i-2, i-1, i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_DOT_STR_CUBE:
|
||||
assert(i == 3);
|
||||
sampler_type = "samplerCube";
|
||||
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_STR_CUBE */\n");
|
||||
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_STR_CUBE */\n");
|
||||
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i, dotmap_func, ps->input_tex[i]);
|
||||
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, vec3(dot%d, dot%d, dot%d));\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, vec3(dot%d, dot%d, dot%d));\n",
|
||||
i, i, i-2, i-1, i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_DPNDNT_AR:
|
||||
assert(i >= 1);
|
||||
assert(!ps->state.rect_tex[i]);
|
||||
sampler_type = "sampler2D";
|
||||
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, t%d.ar);\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, t%d.ar);\n",
|
||||
i, i, ps->input_tex[i]);
|
||||
break;
|
||||
case PS_TEXTUREMODES_DPNDNT_GB:
|
||||
assert(i >= 1);
|
||||
assert(!ps->state.rect_tex[i]);
|
||||
sampler_type = "sampler2D";
|
||||
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, t%d.gb);\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, t%d.gb);\n",
|
||||
i, i, ps->input_tex[i]);
|
||||
break;
|
||||
case PS_TEXTUREMODES_DOTPRODUCT:
|
||||
assert(i == 1 || i == 2);
|
||||
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOTPRODUCT */\n");
|
||||
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOTPRODUCT */\n");
|
||||
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i, dotmap_func, ps->input_tex[i]);
|
||||
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0);\n", i);
|
||||
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0);\n", i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_DOT_RFLCT_SPEC_CONST:
|
||||
assert(i == 3);
|
||||
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_DOT_RFLCT_SPEC_CONST */\n",
|
||||
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_DOT_RFLCT_SPEC_CONST */\n",
|
||||
i);
|
||||
NV2A_UNIMPLEMENTED("PS_TEXTUREMODES_DOT_RFLCT_SPEC_CONST");
|
||||
break;
|
||||
|
@ -868,11 +868,11 @@ static QString* psh_convert(struct PixelShader *ps)
|
|||
}
|
||||
|
||||
if (sampler_type != NULL) {
|
||||
qstring_append_fmt(preflight, "uniform %s texSamp%d;\n", sampler_type, i);
|
||||
mstring_append_fmt(preflight, "uniform %s texSamp%d;\n", sampler_type, i);
|
||||
|
||||
/* As this means a texture fetch does happen, do alphakill */
|
||||
if (ps->state.alphakill[i]) {
|
||||
qstring_append_fmt(vars, "if (t%d.a == 0.0) { discard; };\n",
|
||||
mstring_append_fmt(vars, "if (t%d.a == 0.0) { discard; };\n",
|
||||
i);
|
||||
}
|
||||
}
|
||||
|
@ -880,21 +880,21 @@ static QString* psh_convert(struct PixelShader *ps)
|
|||
|
||||
for (i = 0; i < ps->num_stages; i++) {
|
||||
ps->cur_stage = i;
|
||||
qstring_append_fmt(ps->code, "// Stage %d\n", i);
|
||||
mstring_append_fmt(ps->code, "// Stage %d\n", i);
|
||||
add_stage_code(ps, ps->stage[i].rgb_input, ps->stage[i].rgb_output, "rgb", false);
|
||||
add_stage_code(ps, ps->stage[i].alpha_input, ps->stage[i].alpha_output, "a", true);
|
||||
}
|
||||
|
||||
if (ps->final_input.enabled) {
|
||||
ps->cur_stage = 8;
|
||||
qstring_append(ps->code, "// Final Combiner\n");
|
||||
mstring_append(ps->code, "// Final Combiner\n");
|
||||
add_final_stage_code(ps, ps->final_input);
|
||||
}
|
||||
|
||||
if (ps->state.alpha_test && ps->state.alpha_func != ALPHA_FUNC_ALWAYS) {
|
||||
qstring_append_fmt(preflight, "uniform float alphaRef;\n");
|
||||
mstring_append_fmt(preflight, "uniform float alphaRef;\n");
|
||||
if (ps->state.alpha_func == ALPHA_FUNC_NEVER) {
|
||||
qstring_append(ps->code, "discard;\n");
|
||||
mstring_append(ps->code, "discard;\n");
|
||||
} else {
|
||||
const char* alpha_op;
|
||||
switch (ps->state.alpha_func) {
|
||||
|
@ -908,38 +908,38 @@ static QString* psh_convert(struct PixelShader *ps)
|
|||
assert(false);
|
||||
break;
|
||||
}
|
||||
qstring_append_fmt(ps->code, "if (!(fragColor.a %s alphaRef)) discard;\n",
|
||||
mstring_append_fmt(ps->code, "if (!(fragColor.a %s alphaRef)) discard;\n",
|
||||
alpha_op);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ps->num_const_refs; i++) {
|
||||
qstring_append_fmt(preflight, "uniform vec4 %s;\n", ps->const_refs[i]);
|
||||
mstring_append_fmt(preflight, "uniform vec4 %s;\n", ps->const_refs[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < ps->num_var_refs; i++) {
|
||||
qstring_append_fmt(vars, "vec4 %s;\n", ps->var_refs[i]);
|
||||
mstring_append_fmt(vars, "vec4 %s;\n", ps->var_refs[i]);
|
||||
if (strcmp(ps->var_refs[i], "r0") == 0) {
|
||||
if (ps->tex_modes[0] != PS_TEXTUREMODES_NONE) {
|
||||
qstring_append(vars, "r0.a = t0.a;\n");
|
||||
mstring_append(vars, "r0.a = t0.a;\n");
|
||||
} else {
|
||||
qstring_append(vars, "r0.a = 1.0;\n");
|
||||
mstring_append(vars, "r0.a = 1.0;\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString *final = qstring_new();
|
||||
qstring_append(final, "#version 330\n\n");
|
||||
qstring_append(final, qstring_get_str(preflight));
|
||||
qstring_append(final, "void main() {\n");
|
||||
qstring_append(final, qstring_get_str(clip));
|
||||
qstring_append(final, qstring_get_str(vars));
|
||||
qstring_append(final, qstring_get_str(ps->code));
|
||||
qstring_append(final, "}\n");
|
||||
MString *final = mstring_new();
|
||||
mstring_append(final, "#version 330\n\n");
|
||||
mstring_append(final, mstring_get_str(preflight));
|
||||
mstring_append(final, "void main() {\n");
|
||||
mstring_append(final, mstring_get_str(clip));
|
||||
mstring_append(final, mstring_get_str(vars));
|
||||
mstring_append(final, mstring_get_str(ps->code));
|
||||
mstring_append(final, "}\n");
|
||||
|
||||
qobject_unref(preflight);
|
||||
qobject_unref(vars);
|
||||
qobject_unref(ps->code);
|
||||
mstring_unref(preflight);
|
||||
mstring_unref(vars);
|
||||
mstring_unref(ps->code);
|
||||
|
||||
return final;
|
||||
}
|
||||
|
@ -976,7 +976,7 @@ static void parse_combiner_output(uint32_t value, struct OutputInfo *out)
|
|||
out->cd_alphablue = flags & 0x40;
|
||||
}
|
||||
|
||||
QString *psh_translate(const PshState state)
|
||||
MString *psh_translate(const PshState state)
|
||||
{
|
||||
int i;
|
||||
struct PixelShader ps;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef HW_NV2A_PSH_H
|
||||
#define HW_NV2A_PSH_H
|
||||
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "shaders_common.h"
|
||||
|
||||
enum PshAlphaFunc {
|
||||
ALPHA_FUNC_NEVER,
|
||||
|
@ -63,6 +63,6 @@ typedef struct PshState {
|
|||
unsigned int window_clip_count;
|
||||
} PshState;
|
||||
|
||||
QString *psh_translate(const PshState state);
|
||||
MString *psh_translate(const PshState state);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,26 +25,26 @@
|
|||
#include "shaders_common.h"
|
||||
#include "shaders.h"
|
||||
|
||||
void qstring_append_fmt(QString *qstring, const char *fmt, ...)
|
||||
void mstring_append_fmt(MString *qstring, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
qstring_append_va(qstring, fmt, ap);
|
||||
mstring_append_va(qstring, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
QString *qstring_from_fmt(const char *fmt, ...)
|
||||
MString *mstring_from_fmt(const char *fmt, ...)
|
||||
{
|
||||
QString *ret = qstring_new();
|
||||
MString *ret = mstring_new();
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
qstring_append_va(ret, fmt, ap);
|
||||
mstring_append_va(ret, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void qstring_append_va(QString *qstring, const char *fmt, va_list va)
|
||||
void mstring_append_va(MString *qstring, const char *fmt, va_list va)
|
||||
{
|
||||
char scratch[256];
|
||||
|
||||
|
@ -56,7 +56,7 @@ void qstring_append_va(QString *qstring, const char *fmt, va_list va)
|
|||
if (len == 0) {
|
||||
return;
|
||||
} else if (len < sizeof(scratch)) {
|
||||
qstring_append(qstring, scratch);
|
||||
mstring_append(qstring, scratch);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -66,11 +66,11 @@ void qstring_append_va(QString *qstring, const char *fmt, va_list va)
|
|||
vsnprintf(buf, len + 1, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
qstring_append(qstring, buf);
|
||||
mstring_append(qstring, buf);
|
||||
g_free(buf);
|
||||
}
|
||||
|
||||
static QString* generate_geometry_shader(
|
||||
static MString* generate_geometry_shader(
|
||||
enum ShaderPolygonMode polygon_front_mode,
|
||||
enum ShaderPolygonMode polygon_back_mode,
|
||||
enum ShaderPrimitiveMode primitive_mode,
|
||||
|
@ -212,11 +212,11 @@ static QString* generate_geometry_shader(
|
|||
assert(layout_in);
|
||||
assert(layout_out);
|
||||
assert(body);
|
||||
QString* s = qstring_from_str("#version 330\n"
|
||||
MString* s = mstring_from_str("#version 330\n"
|
||||
"\n");
|
||||
qstring_append(s, layout_in);
|
||||
qstring_append(s, layout_out);
|
||||
qstring_append(s, "\n"
|
||||
mstring_append(s, layout_in);
|
||||
mstring_append(s, layout_out);
|
||||
mstring_append(s, "\n"
|
||||
STRUCT_VERTEX_DATA
|
||||
"noperspective in VertexData v_vtx[];\n"
|
||||
"noperspective out VertexData g_vtx;\n"
|
||||
|
@ -229,48 +229,48 @@ static QString* generate_geometry_shader(
|
|||
"}\n"
|
||||
"\n"
|
||||
"void main() {\n");
|
||||
qstring_append(s, body);
|
||||
qstring_append(s, "}\n");
|
||||
mstring_append(s, body);
|
||||
mstring_append(s, "}\n");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void append_skinning_code(QString* str, bool mix,
|
||||
static void append_skinning_code(MString* str, bool mix,
|
||||
unsigned int count, const char* type,
|
||||
const char* output, const char* input,
|
||||
const char* matrix, const char* swizzle)
|
||||
{
|
||||
|
||||
if (count == 0) {
|
||||
qstring_append_fmt(str, "%s %s = (%s * %s0).%s;\n",
|
||||
mstring_append_fmt(str, "%s %s = (%s * %s0).%s;\n",
|
||||
type, output, input, matrix, swizzle);
|
||||
} else {
|
||||
qstring_append_fmt(str, "%s %s = %s(0.0);\n", type, output, type);
|
||||
mstring_append_fmt(str, "%s %s = %s(0.0);\n", type, output, type);
|
||||
if (mix) {
|
||||
/* Generated final weight (like GL_WEIGHT_SUM_UNITY_ARB) */
|
||||
qstring_append(str, "{\n"
|
||||
mstring_append(str, "{\n"
|
||||
" float weight_i;\n"
|
||||
" float weight_n = 1.0;\n");
|
||||
int i;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (i < (count - 1)) {
|
||||
char c = "xyzw"[i];
|
||||
qstring_append_fmt(str, " weight_i = weight.%c;\n"
|
||||
mstring_append_fmt(str, " weight_i = weight.%c;\n"
|
||||
" weight_n -= weight_i;\n",
|
||||
c);
|
||||
} else {
|
||||
qstring_append(str, " weight_i = weight_n;\n");
|
||||
mstring_append(str, " weight_i = weight_n;\n");
|
||||
}
|
||||
qstring_append_fmt(str, " %s += (%s * %s%d).%s * weight_i;\n",
|
||||
mstring_append_fmt(str, " %s += (%s * %s%d).%s * weight_i;\n",
|
||||
output, input, matrix, i, swizzle);
|
||||
}
|
||||
qstring_append(str, "}\n");
|
||||
mstring_append(str, "}\n");
|
||||
} else {
|
||||
/* Individual weights */
|
||||
int i;
|
||||
for (i = 0; i < count; i++) {
|
||||
char c = "xyzw"[i];
|
||||
qstring_append_fmt(str, "%s += (%s * %s%d).%s * weight.%c;\n",
|
||||
mstring_append_fmt(str, "%s += (%s * %s%d).%s * weight.%c;\n",
|
||||
output, input, matrix, i, swizzle, c);
|
||||
}
|
||||
assert(false); /* FIXME: Untested */
|
||||
|
@ -288,12 +288,12 @@ static void append_skinning_code(QString* str, bool mix,
|
|||
#define GLSL_DEFINE(a, b) "#define " stringify(a) " " b "\n"
|
||||
|
||||
static void generate_fixed_function(const ShaderState state,
|
||||
QString *header, QString *body)
|
||||
MString *header, MString *body)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
/* generate vertex shader mimicking fixed function */
|
||||
qstring_append(header,
|
||||
mstring_append(header,
|
||||
"#define position v0\n"
|
||||
"#define weight v1\n"
|
||||
"#define normal v2.xyz\n"
|
||||
|
@ -393,7 +393,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
assert(false);
|
||||
break;
|
||||
}
|
||||
qstring_append_fmt(body, "/* Skinning mode %d */\n",
|
||||
mstring_append_fmt(body, "/* Skinning mode %d */\n",
|
||||
state.skinning);
|
||||
|
||||
append_skinning_code(body, mix, count, "vec4",
|
||||
|
@ -405,12 +405,12 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
|
||||
/* Normalization */
|
||||
if (state.normalization) {
|
||||
qstring_append(body, "tNormal = normalize(tNormal);\n");
|
||||
mstring_append(body, "tNormal = normalize(tNormal);\n");
|
||||
}
|
||||
|
||||
/* Texgen */
|
||||
for (i = 0; i < NV2A_MAX_TEXTURES; i++) {
|
||||
qstring_append_fmt(body, "/* Texgen for stage %d */\n",
|
||||
mstring_append_fmt(body, "/* Texgen for stage %d */\n",
|
||||
i);
|
||||
/* Set each component individually */
|
||||
/* FIXME: could be nicer if some channels share the same texgen */
|
||||
|
@ -420,25 +420,25 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
char cSuffix = "STRQ"[j];
|
||||
switch (state.texgen[i][j]) {
|
||||
case TEXGEN_DISABLE:
|
||||
qstring_append_fmt(body, "oT%d.%c = texture%d.%c;\n",
|
||||
mstring_append_fmt(body, "oT%d.%c = texture%d.%c;\n",
|
||||
i, c, i, c);
|
||||
break;
|
||||
case TEXGEN_EYE_LINEAR:
|
||||
qstring_append_fmt(body, "oT%d.%c = dot(texPlane%c%d, tPosition);\n",
|
||||
mstring_append_fmt(body, "oT%d.%c = dot(texPlane%c%d, tPosition);\n",
|
||||
i, c, cSuffix, i);
|
||||
break;
|
||||
case TEXGEN_OBJECT_LINEAR:
|
||||
qstring_append_fmt(body, "oT%d.%c = dot(texPlane%c%d, position);\n",
|
||||
mstring_append_fmt(body, "oT%d.%c = dot(texPlane%c%d, position);\n",
|
||||
i, c, cSuffix, i);
|
||||
assert(false); /* Untested */
|
||||
break;
|
||||
case TEXGEN_SPHERE_MAP:
|
||||
assert(j < 2); /* Channels S,T only! */
|
||||
qstring_append(body, "{\n");
|
||||
mstring_append(body, "{\n");
|
||||
/* FIXME: u, r and m only have to be calculated once */
|
||||
qstring_append(body, " vec3 u = normalize(tPosition.xyz);\n");
|
||||
mstring_append(body, " vec3 u = normalize(tPosition.xyz);\n");
|
||||
//FIXME: tNormal before or after normalization? Always normalize?
|
||||
qstring_append(body, " vec3 r = reflect(u, tNormal);\n");
|
||||
mstring_append(body, " vec3 r = reflect(u, tNormal);\n");
|
||||
|
||||
/* FIXME: This would consume 1 division fewer and *might* be
|
||||
* faster than length:
|
||||
|
@ -447,24 +447,24 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
* float m = inversesqrt(dot(ro,ro))*0.5;
|
||||
*/
|
||||
|
||||
qstring_append(body, " float invM = 1.0 / (2.0 * length(r + vec3(0.0, 0.0, 1.0)));\n");
|
||||
qstring_append_fmt(body, " oT%d.%c = r.%c * invM + 0.5;\n",
|
||||
mstring_append(body, " float invM = 1.0 / (2.0 * length(r + vec3(0.0, 0.0, 1.0)));\n");
|
||||
mstring_append_fmt(body, " oT%d.%c = r.%c * invM + 0.5;\n",
|
||||
i, c, c);
|
||||
qstring_append(body, "}\n");
|
||||
mstring_append(body, "}\n");
|
||||
break;
|
||||
case TEXGEN_REFLECTION_MAP:
|
||||
assert(j < 3); /* Channels S,T,R only! */
|
||||
qstring_append(body, "{\n");
|
||||
mstring_append(body, "{\n");
|
||||
/* FIXME: u and r only have to be calculated once, can share the one from SPHERE_MAP */
|
||||
qstring_append(body, " vec3 u = normalize(tPosition.xyz);\n");
|
||||
qstring_append(body, " vec3 r = reflect(u, tNormal);\n");
|
||||
qstring_append_fmt(body, " oT%d.%c = r.%c;\n",
|
||||
mstring_append(body, " vec3 u = normalize(tPosition.xyz);\n");
|
||||
mstring_append(body, " vec3 r = reflect(u, tNormal);\n");
|
||||
mstring_append_fmt(body, " oT%d.%c = r.%c;\n",
|
||||
i, c, c);
|
||||
qstring_append(body, "}\n");
|
||||
mstring_append(body, "}\n");
|
||||
break;
|
||||
case TEXGEN_NORMAL_MAP:
|
||||
assert(j < 3); /* Channels S,T,R only! */
|
||||
qstring_append_fmt(body, "oT%d.%c = tNormal.%c;\n",
|
||||
mstring_append_fmt(body, "oT%d.%c = tNormal.%c;\n",
|
||||
i, c, c);
|
||||
break;
|
||||
default:
|
||||
|
@ -477,7 +477,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
/* Apply texture matrices */
|
||||
for (i = 0; i < NV2A_MAX_TEXTURES; i++) {
|
||||
if (state.texture_matrix_enable[i]) {
|
||||
qstring_append_fmt(body,
|
||||
mstring_append_fmt(body,
|
||||
"oT%d = oT%d * texMat%d;\n",
|
||||
i, i, i);
|
||||
}
|
||||
|
@ -489,23 +489,23 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
//FIXME: Do 2 passes if we want 2 sided-lighting?
|
||||
|
||||
if (state.ambient_src == MATERIAL_COLOR_SRC_MATERIAL) {
|
||||
qstring_append(body, "oD0 = vec4(sceneAmbientColor, diffuse.a);\n");
|
||||
mstring_append(body, "oD0 = vec4(sceneAmbientColor, diffuse.a);\n");
|
||||
} else if (state.ambient_src == MATERIAL_COLOR_SRC_DIFFUSE) {
|
||||
qstring_append(body, "oD0 = vec4(diffuse.rgb, diffuse.a);\n");
|
||||
mstring_append(body, "oD0 = vec4(diffuse.rgb, diffuse.a);\n");
|
||||
} else if (state.ambient_src == MATERIAL_COLOR_SRC_SPECULAR) {
|
||||
qstring_append(body, "oD0 = vec4(specular.rgb, diffuse.a);\n");
|
||||
mstring_append(body, "oD0 = vec4(specular.rgb, diffuse.a);\n");
|
||||
}
|
||||
|
||||
qstring_append(body, "oD0.rgb *= materialEmissionColor.rgb;\n");
|
||||
mstring_append(body, "oD0.rgb *= materialEmissionColor.rgb;\n");
|
||||
if (state.emission_src == MATERIAL_COLOR_SRC_MATERIAL) {
|
||||
qstring_append(body, "oD0.rgb += sceneAmbientColor;\n");
|
||||
mstring_append(body, "oD0.rgb += sceneAmbientColor;\n");
|
||||
} else if (state.emission_src == MATERIAL_COLOR_SRC_DIFFUSE) {
|
||||
qstring_append(body, "oD0.rgb += diffuse.rgb;\n");
|
||||
mstring_append(body, "oD0.rgb += diffuse.rgb;\n");
|
||||
} else if (state.emission_src == MATERIAL_COLOR_SRC_SPECULAR) {
|
||||
qstring_append(body, "oD0.rgb += specular.rgb;\n");
|
||||
mstring_append(body, "oD0.rgb += specular.rgb;\n");
|
||||
}
|
||||
|
||||
qstring_append(body, "oD1 = vec4(0.0, 0.0, 0.0, specular.a);\n");
|
||||
mstring_append(body, "oD1 = vec4(0.0, 0.0, 0.0, specular.a);\n");
|
||||
|
||||
for (i = 0; i < NV2A_MAX_LIGHTS; i++) {
|
||||
if (state.light[i] == LIGHT_OFF) {
|
||||
|
@ -518,16 +518,16 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
* colors
|
||||
*/
|
||||
|
||||
qstring_append_fmt(body, "/* Light %d */ {\n", i);
|
||||
mstring_append_fmt(body, "/* Light %d */ {\n", i);
|
||||
|
||||
if (state.light[i] == LIGHT_LOCAL
|
||||
|| state.light[i] == LIGHT_SPOT) {
|
||||
|
||||
qstring_append_fmt(header,
|
||||
mstring_append_fmt(header,
|
||||
"uniform vec3 lightLocalPosition%d;\n"
|
||||
"uniform vec3 lightLocalAttenuation%d;\n",
|
||||
i, i);
|
||||
qstring_append_fmt(body,
|
||||
mstring_append_fmt(body,
|
||||
" vec3 VP = lightLocalPosition%d - tPosition.xyz/tPosition.w;\n"
|
||||
" float d = length(VP);\n"
|
||||
//FIXME: if (d > lightLocalRange) { .. don't process this light .. } /* inclusive?! */ - what about directional lights?
|
||||
|
@ -547,11 +547,11 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
|
||||
/* lightLocalRange will be 1e+30 here */
|
||||
|
||||
qstring_append_fmt(header,
|
||||
mstring_append_fmt(header,
|
||||
"uniform vec3 lightInfiniteHalfVector%d;\n"
|
||||
"uniform vec3 lightInfiniteDirection%d;\n",
|
||||
i, i);
|
||||
qstring_append_fmt(body,
|
||||
mstring_append_fmt(body,
|
||||
" float attenuation = 1.0;\n"
|
||||
" float nDotVP = max(0.0, dot(tNormal, normalize(vec3(lightInfiniteDirection%d))));\n"
|
||||
" float nDotHV = max(0.0, dot(tNormal, vec3(lightInfiniteHalfVector%d)));\n",
|
||||
|
@ -574,7 +574,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
break;
|
||||
}
|
||||
|
||||
qstring_append_fmt(body,
|
||||
mstring_append_fmt(body,
|
||||
" float pf;\n"
|
||||
" if (nDotVP == 0.0) {\n"
|
||||
" pf = 0.0;\n"
|
||||
|
@ -586,23 +586,23 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
" vec3 lightSpecular = lightSpecularColor(%d) * pf;\n",
|
||||
i, i, i);
|
||||
|
||||
qstring_append(body,
|
||||
mstring_append(body,
|
||||
" oD0.xyz += lightAmbient;\n");
|
||||
|
||||
qstring_append(body,
|
||||
mstring_append(body,
|
||||
" oD0.xyz += diffuse.xyz * lightDiffuse;\n");
|
||||
|
||||
qstring_append(body,
|
||||
mstring_append(body,
|
||||
" oD1.xyz += specular.xyz * lightSpecular;\n");
|
||||
|
||||
qstring_append(body, "}\n");
|
||||
mstring_append(body, "}\n");
|
||||
}
|
||||
} else {
|
||||
qstring_append(body, " oD0 = diffuse;\n");
|
||||
qstring_append(body, " oD1 = specular;\n");
|
||||
mstring_append(body, " oD0 = diffuse;\n");
|
||||
mstring_append(body, " oD1 = specular;\n");
|
||||
}
|
||||
qstring_append(body, " oB0 = backDiffuse;\n");
|
||||
qstring_append(body, " oB1 = backSpecular;\n");
|
||||
mstring_append(body, " oB0 = backDiffuse;\n");
|
||||
mstring_append(body, " oB1 = backSpecular;\n");
|
||||
|
||||
/* Fog */
|
||||
if (state.fog_enable) {
|
||||
|
@ -611,20 +611,20 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
switch(state.foggen) {
|
||||
case FOGGEN_SPEC_ALPHA:
|
||||
/* FIXME: Do we have to clamp here? */
|
||||
qstring_append(body, " float fogDistance = clamp(specular.a, 0.0, 1.0);\n");
|
||||
mstring_append(body, " float fogDistance = clamp(specular.a, 0.0, 1.0);\n");
|
||||
break;
|
||||
case FOGGEN_RADIAL:
|
||||
qstring_append(body, " float fogDistance = length(tPosition.xyz);\n");
|
||||
mstring_append(body, " float fogDistance = length(tPosition.xyz);\n");
|
||||
break;
|
||||
case FOGGEN_PLANAR:
|
||||
case FOGGEN_ABS_PLANAR:
|
||||
qstring_append(body, " float fogDistance = dot(fogPlane.xyz, tPosition.xyz) + fogPlane.w;\n");
|
||||
mstring_append(body, " float fogDistance = dot(fogPlane.xyz, tPosition.xyz) + fogPlane.w;\n");
|
||||
if (state.foggen == FOGGEN_ABS_PLANAR) {
|
||||
qstring_append(body, " fogDistance = abs(fogDistance);\n");
|
||||
mstring_append(body, " fogDistance = abs(fogDistance);\n");
|
||||
}
|
||||
break;
|
||||
case FOGGEN_FOG_X:
|
||||
qstring_append(body, " float fogDistance = fogCoord;\n");
|
||||
mstring_append(body, " float fogDistance = fogCoord;\n");
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
|
@ -635,22 +635,22 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
|
||||
/* If skinning is off the composite matrix already includes the MV matrix */
|
||||
if (state.skinning == SKINNING_OFF) {
|
||||
qstring_append(body, " tPosition = position;\n");
|
||||
mstring_append(body, " tPosition = position;\n");
|
||||
}
|
||||
|
||||
qstring_append(body,
|
||||
mstring_append(body,
|
||||
" oPos = invViewport * (tPosition * compositeMat);\n"
|
||||
" oPos.z = oPos.z * 2.0 - oPos.w;\n");
|
||||
|
||||
qstring_append(body, " vtx.inv_w = 1.0 / oPos.w;\n");
|
||||
mstring_append(body, " vtx.inv_w = 1.0 / oPos.w;\n");
|
||||
|
||||
}
|
||||
|
||||
static QString *generate_vertex_shader(const ShaderState state,
|
||||
static MString *generate_vertex_shader(const ShaderState state,
|
||||
char vtx_prefix)
|
||||
{
|
||||
int i;
|
||||
QString *header = qstring_from_str(
|
||||
MString *header = mstring_from_str(
|
||||
"#version 400\n"
|
||||
"\n"
|
||||
"uniform vec2 clipRange;\n"
|
||||
|
@ -704,27 +704,27 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT))
|
|||
"}\n"
|
||||
STRUCT_VERTEX_DATA);
|
||||
|
||||
qstring_append_fmt(header, "noperspective out VertexData %c_vtx;\n",
|
||||
mstring_append_fmt(header, "noperspective out VertexData %c_vtx;\n",
|
||||
vtx_prefix);
|
||||
qstring_append_fmt(header, "#define vtx %c_vtx\n",
|
||||
mstring_append_fmt(header, "#define vtx %c_vtx\n",
|
||||
vtx_prefix);
|
||||
qstring_append(header, "\n");
|
||||
mstring_append(header, "\n");
|
||||
for (i = 0; i < NV2A_VERTEXSHADER_ATTRIBUTES; i++) {
|
||||
if (state.compressed_attrs & (1 << i)) {
|
||||
qstring_append_fmt(header,
|
||||
mstring_append_fmt(header,
|
||||
"layout(location = %d) in int v%d_cmp;\n", i, i);
|
||||
} else {
|
||||
qstring_append_fmt(header, "layout(location = %d) in vec4 v%d;\n",
|
||||
mstring_append_fmt(header, "layout(location = %d) in vec4 v%d;\n",
|
||||
i, i);
|
||||
}
|
||||
}
|
||||
qstring_append(header, "\n");
|
||||
mstring_append(header, "\n");
|
||||
|
||||
QString *body = qstring_from_str("void main() {\n");
|
||||
MString *body = mstring_from_str("void main() {\n");
|
||||
|
||||
for (i = 0; i < NV2A_VERTEXSHADER_ATTRIBUTES; i++) {
|
||||
if (state.compressed_attrs & (1 << i)) {
|
||||
qstring_append_fmt(
|
||||
mstring_append_fmt(
|
||||
body, "vec4 v%d = decompress_11_11_10(v%d_cmp);\n", i, i);
|
||||
}
|
||||
}
|
||||
|
@ -754,7 +754,7 @@ STRUCT_VERTEX_DATA);
|
|||
* state.vertex_program = true; state.foggen == FOGGEN_PLANAR
|
||||
* but expects oFog.x as fogdistance?! Writes oFog.xyzw = v0.z
|
||||
*/
|
||||
qstring_append(body, " float fogDistance = oFog.x;\n");
|
||||
mstring_append(body, " float fogDistance = oFog.x;\n");
|
||||
}
|
||||
|
||||
/* FIXME: Do this per pixel? */
|
||||
|
@ -768,8 +768,8 @@ STRUCT_VERTEX_DATA);
|
|||
* fogParam[0] = 1 + end * fogParam[1];
|
||||
*/
|
||||
|
||||
qstring_append(body, " float fogFactor = fogParam[0] + fogDistance * fogParam[1];\n");
|
||||
qstring_append(body, " fogFactor -= 1.0;\n"); /* FIXME: WHHYYY?!! */
|
||||
mstring_append(body, " float fogFactor = fogParam[0] + fogDistance * fogParam[1];\n");
|
||||
mstring_append(body, " fogFactor -= 1.0;\n"); /* FIXME: WHHYYY?!! */
|
||||
break;
|
||||
case FOG_MODE_EXP:
|
||||
case FOG_MODE_EXP_ABS:
|
||||
|
@ -779,8 +779,8 @@ STRUCT_VERTEX_DATA);
|
|||
* fogParam[0] = 1.5
|
||||
*/
|
||||
|
||||
qstring_append(body, " float fogFactor = fogParam[0] + exp2(fogDistance * fogParam[1] * 16.0);\n");
|
||||
qstring_append(body, " fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */
|
||||
mstring_append(body, " float fogFactor = fogParam[0] + exp2(fogDistance * fogParam[1] * 16.0);\n");
|
||||
mstring_append(body, " fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */
|
||||
break;
|
||||
case FOG_MODE_EXP2:
|
||||
case FOG_MODE_EXP2_ABS:
|
||||
|
@ -790,8 +790,8 @@ STRUCT_VERTEX_DATA);
|
|||
* fogParam[0] = 1.5
|
||||
*/
|
||||
|
||||
qstring_append(body, " float fogFactor = fogParam[0] + exp2(-fogDistance * fogDistance * fogParam[1] * fogParam[1] * 32.0);\n");
|
||||
qstring_append(body, " fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */
|
||||
mstring_append(body, " float fogFactor = fogParam[0] + exp2(-fogDistance * fogDistance * fogParam[1] * fogParam[1] * 32.0);\n");
|
||||
mstring_append(body, " fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
|
@ -802,21 +802,21 @@ STRUCT_VERTEX_DATA);
|
|||
case FOG_MODE_LINEAR_ABS:
|
||||
case FOG_MODE_EXP_ABS:
|
||||
case FOG_MODE_EXP2_ABS:
|
||||
qstring_append(body, " fogFactor = abs(fogFactor);\n");
|
||||
mstring_append(body, " fogFactor = abs(fogFactor);\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* FIXME: What about fog alpha?! */
|
||||
qstring_append(body, " oFog.xyzw = vec4(fogFactor);\n");
|
||||
mstring_append(body, " oFog.xyzw = vec4(fogFactor);\n");
|
||||
} else {
|
||||
/* FIXME: Is the fog still calculated / passed somehow?!
|
||||
*/
|
||||
qstring_append(body, " oFog.xyzw = vec4(1.0);\n");
|
||||
mstring_append(body, " oFog.xyzw = vec4(1.0);\n");
|
||||
}
|
||||
|
||||
/* Set outputs */
|
||||
qstring_append(body, "\n"
|
||||
mstring_append(body, "\n"
|
||||
" vtx.D0 = clamp(oD0, 0.0, 1.0) * vtx.inv_w;\n"
|
||||
" vtx.D1 = clamp(oD1, 0.0, 1.0) * vtx.inv_w;\n"
|
||||
" vtx.B0 = clamp(oB0, 0.0, 1.0) * vtx.inv_w;\n"
|
||||
|
@ -833,8 +833,8 @@ STRUCT_VERTEX_DATA);
|
|||
|
||||
|
||||
/* Return combined header + source */
|
||||
qstring_append(header, qstring_get_str(body));
|
||||
qobject_unref(body);
|
||||
mstring_append(header, mstring_get_str(body));
|
||||
mstring_unref(body);
|
||||
return header;
|
||||
|
||||
}
|
||||
|
@ -884,40 +884,40 @@ ShaderBinding* generate_shaders(const ShaderState state)
|
|||
|
||||
/* Create an option geometry shader and find primitive type */
|
||||
GLenum gl_primitive_mode;
|
||||
QString* geometry_shader_code =
|
||||
MString* geometry_shader_code =
|
||||
generate_geometry_shader(state.polygon_front_mode,
|
||||
state.polygon_back_mode,
|
||||
state.primitive_mode,
|
||||
&gl_primitive_mode);
|
||||
if (geometry_shader_code) {
|
||||
const char* geometry_shader_code_str =
|
||||
qstring_get_str(geometry_shader_code);
|
||||
mstring_get_str(geometry_shader_code);
|
||||
GLuint geometry_shader = create_gl_shader(GL_GEOMETRY_SHADER,
|
||||
geometry_shader_code_str,
|
||||
"geometry shader");
|
||||
glAttachShader(program, geometry_shader);
|
||||
qobject_unref(geometry_shader_code);
|
||||
mstring_unref(geometry_shader_code);
|
||||
vtx_prefix = 'v';
|
||||
} else {
|
||||
vtx_prefix = 'g';
|
||||
}
|
||||
|
||||
/* create the vertex shader */
|
||||
QString *vertex_shader_code = generate_vertex_shader(state, vtx_prefix);
|
||||
MString *vertex_shader_code = generate_vertex_shader(state, vtx_prefix);
|
||||
GLuint vertex_shader = create_gl_shader(GL_VERTEX_SHADER,
|
||||
qstring_get_str(vertex_shader_code),
|
||||
mstring_get_str(vertex_shader_code),
|
||||
"vertex shader");
|
||||
glAttachShader(program, vertex_shader);
|
||||
qobject_unref(vertex_shader_code);
|
||||
mstring_unref(vertex_shader_code);
|
||||
|
||||
/* generate a fragment shader from register combiners */
|
||||
QString *fragment_shader_code = psh_translate(state.psh);
|
||||
const char *fragment_shader_code_str = qstring_get_str(fragment_shader_code);
|
||||
MString *fragment_shader_code = psh_translate(state.psh);
|
||||
const char *fragment_shader_code_str = mstring_get_str(fragment_shader_code);
|
||||
GLuint fragment_shader = create_gl_shader(GL_FRAGMENT_SHADER,
|
||||
fragment_shader_code_str,
|
||||
"fragment shader");
|
||||
glAttachShader(program, fragment_shader);
|
||||
qobject_unref(fragment_shader_code);
|
||||
mstring_unref(fragment_shader_code);
|
||||
|
||||
/* link the program */
|
||||
glLinkProgram(program);
|
||||
|
|
|
@ -37,8 +37,80 @@
|
|||
"};\n"
|
||||
|
||||
|
||||
void qstring_append_fmt(QString *qstring, const char *fmt, ...);
|
||||
QString *qstring_from_fmt(const char *fmt, ...);
|
||||
void qstring_append_va(QString *qstring, const char *fmt, va_list va);
|
||||
typedef struct {
|
||||
int ref;
|
||||
gchar *string;
|
||||
} MString;
|
||||
|
||||
void mstring_append_fmt(MString *mstring, const char *fmt, ...);
|
||||
MString *mstring_from_fmt(const char *fmt, ...);
|
||||
void mstring_append_va(MString *mstring, const char *fmt, va_list va);
|
||||
|
||||
static inline
|
||||
void mstring_ref(MString *mstr)
|
||||
{
|
||||
mstr->ref++;
|
||||
}
|
||||
|
||||
static inline
|
||||
void mstring_unref(MString *mstr)
|
||||
{
|
||||
mstr->ref--;
|
||||
if (!mstr->ref) {
|
||||
g_free(mstr->string);
|
||||
g_free(mstr);
|
||||
}
|
||||
}
|
||||
|
||||
static inline
|
||||
void mstring_append(MString *mstr, const char *str)
|
||||
{
|
||||
gchar *n = g_strconcat(mstr->string, str, NULL);
|
||||
g_free(mstr->string);
|
||||
mstr->string = n;
|
||||
}
|
||||
|
||||
static inline
|
||||
void mstring_append_chr(MString *mstr, char chr)
|
||||
{
|
||||
mstring_append_fmt(mstr, "%c", chr);
|
||||
}
|
||||
|
||||
static inline
|
||||
void mstring_append_int(MString *mstr, int val)
|
||||
{
|
||||
mstring_append_fmt(mstr, "%" PRId64, val);
|
||||
}
|
||||
|
||||
static inline
|
||||
MString *mstring_new(void)
|
||||
{
|
||||
MString *mstr = g_malloc(sizeof(MString));
|
||||
mstr->ref = 1;
|
||||
mstr->string = g_strdup("");
|
||||
return mstr;
|
||||
}
|
||||
|
||||
static inline
|
||||
MString *mstring_from_str(const char *str)
|
||||
{
|
||||
MString *mstr = g_malloc(sizeof(MString));
|
||||
mstr->ref = 1;
|
||||
mstr->string = g_strdup(str);
|
||||
return mstr;
|
||||
}
|
||||
|
||||
static inline
|
||||
const gchar *mstring_get_str(MString *mstr)
|
||||
{
|
||||
return mstr->string;
|
||||
}
|
||||
|
||||
static inline
|
||||
size_t mstring_get_length(MString *mstr)
|
||||
{
|
||||
return strlen(mstr->string);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -292,7 +292,7 @@ static int16_t convert_c_register(const int16_t c_reg)
|
|||
|
||||
|
||||
|
||||
static QString* decode_swizzle(const uint32_t *shader_token,
|
||||
static MString* decode_swizzle(const uint32_t *shader_token,
|
||||
VshFieldName swizzle_field)
|
||||
{
|
||||
const char* swizzle_str = "xyzw";
|
||||
|
@ -312,25 +312,25 @@ static QString* decode_swizzle(const uint32_t *shader_token,
|
|||
if (x == SWIZZLE_X && y == SWIZZLE_Y
|
||||
&& z == SWIZZLE_Z && w == SWIZZLE_W) {
|
||||
/* Don't print the swizzle if it's .xyzw */
|
||||
return qstring_from_str(""); // Will turn ".xyzw" into "."
|
||||
return mstring_from_str(""); // Will turn ".xyzw" into "."
|
||||
/* Don't print duplicates */
|
||||
} else if (x == y && y == z && z == w) {
|
||||
return qstring_from_str((char[]){'.', swizzle_str[x], '\0'});
|
||||
return mstring_from_str((char[]){'.', swizzle_str[x], '\0'});
|
||||
} else if (y == z && z == w) {
|
||||
return qstring_from_str((char[]){'.',
|
||||
return mstring_from_str((char[]){'.',
|
||||
swizzle_str[x], swizzle_str[y], '\0'});
|
||||
} else if (z == w) {
|
||||
return qstring_from_str((char[]){'.',
|
||||
return mstring_from_str((char[]){'.',
|
||||
swizzle_str[x], swizzle_str[y], swizzle_str[z], '\0'});
|
||||
} else {
|
||||
return qstring_from_str((char[]){'.',
|
||||
return mstring_from_str((char[]){'.',
|
||||
swizzle_str[x], swizzle_str[y],
|
||||
swizzle_str[z], swizzle_str[w],
|
||||
'\0'}); // Normal swizzle mask
|
||||
}
|
||||
}
|
||||
|
||||
static QString* decode_opcode_input(const uint32_t *shader_token,
|
||||
static MString* decode_opcode_input(const uint32_t *shader_token,
|
||||
VshParameterType param,
|
||||
VshFieldName neg_field,
|
||||
int reg_num)
|
||||
|
@ -339,11 +339,11 @@ static QString* decode_opcode_input(const uint32_t *shader_token,
|
|||
* Input A, B or C is controlled via the Param and NEG fieldnames,
|
||||
* the R-register address for each input is already given by caller. */
|
||||
|
||||
QString *ret_str = qstring_new();
|
||||
MString *ret_str = mstring_new();
|
||||
|
||||
|
||||
if (vsh_get_field(shader_token, neg_field) > 0) {
|
||||
qstring_append_chr(ret_str, '-');
|
||||
mstring_append_chr(ret_str, '-');
|
||||
}
|
||||
|
||||
/* PARAM_R uses the supplied reg_num, but the other two need to be
|
||||
|
@ -371,26 +371,26 @@ static QString* decode_opcode_input(const uint32_t *shader_token,
|
|||
assert(false);
|
||||
break;
|
||||
}
|
||||
qstring_append(ret_str, tmp);
|
||||
mstring_append(ret_str, tmp);
|
||||
|
||||
{
|
||||
/* swizzle bits are next to the neg bit */
|
||||
QString *swizzle_str = decode_swizzle(shader_token, neg_field+1);
|
||||
qstring_append(ret_str, qstring_get_str(swizzle_str));
|
||||
qobject_unref(swizzle_str);
|
||||
MString *swizzle_str = decode_swizzle(shader_token, neg_field+1);
|
||||
mstring_append(ret_str, mstring_get_str(swizzle_str));
|
||||
mstring_unref(swizzle_str);
|
||||
}
|
||||
|
||||
return ret_str;
|
||||
}
|
||||
|
||||
|
||||
static QString* decode_opcode(const uint32_t *shader_token,
|
||||
static MString* decode_opcode(const uint32_t *shader_token,
|
||||
VshOutputMux out_mux,
|
||||
uint32_t mask,
|
||||
const char *opcode,
|
||||
const char *inputs)
|
||||
{
|
||||
QString *ret = qstring_new();
|
||||
MString *ret = mstring_new();
|
||||
int reg_num = vsh_get_field(shader_token, FLD_OUT_R);
|
||||
|
||||
/* Test for paired opcodes (in other words : Are both <> NOP?) */
|
||||
|
@ -410,32 +410,32 @@ static QString* decode_opcode(const uint32_t *shader_token,
|
|||
/* Only if it's not masked away: */
|
||||
&& vsh_get_field(shader_token, FLD_OUT_O_MASK) != 0) {
|
||||
|
||||
qstring_append(ret, " ");
|
||||
qstring_append(ret, opcode);
|
||||
qstring_append(ret, "(");
|
||||
mstring_append(ret, " ");
|
||||
mstring_append(ret, opcode);
|
||||
mstring_append(ret, "(");
|
||||
|
||||
if (vsh_get_field(shader_token, FLD_OUT_ORB) == OUTPUT_C) {
|
||||
/* TODO : Emulate writeable const registers */
|
||||
qstring_append(ret, "c");
|
||||
qstring_append_int(ret,
|
||||
mstring_append(ret, "c");
|
||||
mstring_append_int(ret,
|
||||
convert_c_register(
|
||||
vsh_get_field(shader_token, FLD_OUT_ADDRESS)));
|
||||
} else {
|
||||
qstring_append(ret,
|
||||
mstring_append(ret,
|
||||
out_reg_name[
|
||||
vsh_get_field(shader_token, FLD_OUT_ADDRESS) & 0xF]);
|
||||
}
|
||||
qstring_append(ret,
|
||||
mstring_append(ret,
|
||||
mask_str[
|
||||
vsh_get_field(shader_token, FLD_OUT_O_MASK)]);
|
||||
qstring_append(ret, inputs);
|
||||
qstring_append(ret, ");\n");
|
||||
mstring_append(ret, inputs);
|
||||
mstring_append(ret, ");\n");
|
||||
}
|
||||
|
||||
if (strcmp(opcode, mac_opcode[MAC_ARL]) == 0) {
|
||||
qstring_append_fmt(ret, " ARL(A0%s);\n", inputs);
|
||||
mstring_append_fmt(ret, " ARL(A0%s);\n", inputs);
|
||||
} else if (mask > 0) {
|
||||
qstring_append_fmt(ret, " %s(R%d%s%s);\n",
|
||||
mstring_append_fmt(ret, " %s(R%d%s%s);\n",
|
||||
opcode, reg_num, mask_str[mask], inputs);
|
||||
}
|
||||
|
||||
|
@ -443,12 +443,12 @@ static QString* decode_opcode(const uint32_t *shader_token,
|
|||
}
|
||||
|
||||
|
||||
static QString* decode_token(const uint32_t *shader_token)
|
||||
static MString* decode_token(const uint32_t *shader_token)
|
||||
{
|
||||
QString *ret;
|
||||
MString *ret;
|
||||
|
||||
/* Since it's potentially used twice, decode input C once: */
|
||||
QString *input_c =
|
||||
MString *input_c =
|
||||
decode_opcode_input(shader_token,
|
||||
vsh_get_field(shader_token, FLD_C_MUX),
|
||||
FLD_C_NEG,
|
||||
|
@ -458,30 +458,30 @@ static QString* decode_token(const uint32_t *shader_token)
|
|||
/* See what MAC opcode is written to (if not masked away): */
|
||||
VshMAC mac = vsh_get_field(shader_token, FLD_MAC);
|
||||
if (mac != MAC_NOP) {
|
||||
QString *inputs_mac = qstring_new();
|
||||
MString *inputs_mac = mstring_new();
|
||||
if (mac_opcode_params[mac].A) {
|
||||
QString *input_a =
|
||||
MString *input_a =
|
||||
decode_opcode_input(shader_token,
|
||||
vsh_get_field(shader_token, FLD_A_MUX),
|
||||
FLD_A_NEG,
|
||||
vsh_get_field(shader_token, FLD_A_R));
|
||||
qstring_append(inputs_mac, ", ");
|
||||
qstring_append(inputs_mac, qstring_get_str(input_a));
|
||||
qobject_unref(input_a);
|
||||
mstring_append(inputs_mac, ", ");
|
||||
mstring_append(inputs_mac, mstring_get_str(input_a));
|
||||
mstring_unref(input_a);
|
||||
}
|
||||
if (mac_opcode_params[mac].B) {
|
||||
QString *input_b =
|
||||
MString *input_b =
|
||||
decode_opcode_input(shader_token,
|
||||
vsh_get_field(shader_token, FLD_B_MUX),
|
||||
FLD_B_NEG,
|
||||
vsh_get_field(shader_token, FLD_B_R));
|
||||
qstring_append(inputs_mac, ", ");
|
||||
qstring_append(inputs_mac, qstring_get_str(input_b));
|
||||
qobject_unref(input_b);
|
||||
mstring_append(inputs_mac, ", ");
|
||||
mstring_append(inputs_mac, mstring_get_str(input_b));
|
||||
mstring_unref(input_b);
|
||||
}
|
||||
if (mac_opcode_params[mac].C) {
|
||||
qstring_append(inputs_mac, ", ");
|
||||
qstring_append(inputs_mac, qstring_get_str(input_c));
|
||||
mstring_append(inputs_mac, ", ");
|
||||
mstring_append(inputs_mac, mstring_get_str(input_c));
|
||||
}
|
||||
|
||||
/* Then prepend these inputs with the actual opcode, mask, and input : */
|
||||
|
@ -489,33 +489,33 @@ static QString* decode_token(const uint32_t *shader_token)
|
|||
OMUX_MAC,
|
||||
vsh_get_field(shader_token, FLD_OUT_MAC_MASK),
|
||||
mac_opcode[mac],
|
||||
qstring_get_str(inputs_mac));
|
||||
qobject_unref(inputs_mac);
|
||||
mstring_get_str(inputs_mac));
|
||||
mstring_unref(inputs_mac);
|
||||
} else {
|
||||
ret = qstring_new();
|
||||
ret = mstring_new();
|
||||
}
|
||||
|
||||
/* See if a ILU opcode is present too: */
|
||||
VshILU ilu = vsh_get_field(shader_token, FLD_ILU);
|
||||
if (ilu != ILU_NOP) {
|
||||
QString *inputs_c = qstring_from_str(", ");
|
||||
qstring_append(inputs_c, qstring_get_str(input_c));
|
||||
MString *inputs_c = mstring_from_str(", ");
|
||||
mstring_append(inputs_c, mstring_get_str(input_c));
|
||||
|
||||
/* Append the ILU opcode, mask and (the already determined) input C: */
|
||||
QString *ilu_op =
|
||||
MString *ilu_op =
|
||||
decode_opcode(shader_token,
|
||||
OMUX_ILU,
|
||||
vsh_get_field(shader_token, FLD_OUT_ILU_MASK),
|
||||
ilu_opcode[ilu],
|
||||
qstring_get_str(inputs_c));
|
||||
mstring_get_str(inputs_c));
|
||||
|
||||
qstring_append(ret, qstring_get_str(ilu_op));
|
||||
mstring_append(ret, mstring_get_str(ilu_op));
|
||||
|
||||
qobject_unref(inputs_c);
|
||||
qobject_unref(ilu_op);
|
||||
mstring_unref(inputs_c);
|
||||
mstring_unref(ilu_op);
|
||||
}
|
||||
|
||||
qobject_unref(input_c);
|
||||
mstring_unref(input_c);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -719,24 +719,24 @@ void vsh_translate(uint16_t version,
|
|||
const uint32_t *tokens,
|
||||
unsigned int length,
|
||||
bool z_perspective,
|
||||
QString *header, QString *body)
|
||||
MString *header, MString *body)
|
||||
{
|
||||
|
||||
qstring_append(header, vsh_header);
|
||||
mstring_append(header, vsh_header);
|
||||
|
||||
bool has_final = false;
|
||||
int slot;
|
||||
for (slot=0; slot < length; slot++) {
|
||||
const uint32_t* cur_token = &tokens[slot * VSH_TOKEN_SIZE];
|
||||
QString *token_str = decode_token(cur_token);
|
||||
qstring_append_fmt(body,
|
||||
MString *token_str = decode_token(cur_token);
|
||||
mstring_append_fmt(body,
|
||||
" /* Slot %d: 0x%08X 0x%08X 0x%08X 0x%08X */",
|
||||
slot,
|
||||
cur_token[0],cur_token[1],cur_token[2],cur_token[3]);
|
||||
qstring_append(body, "\n");
|
||||
qstring_append(body, qstring_get_str(token_str));
|
||||
qstring_append(body, "\n");
|
||||
qobject_unref(token_str);
|
||||
mstring_append(body, "\n");
|
||||
mstring_append(body, mstring_get_str(token_str));
|
||||
mstring_append(body, "\n");
|
||||
mstring_unref(token_str);
|
||||
|
||||
if (vsh_get_field(cur_token, FLD_FINAL)) {
|
||||
has_final = true;
|
||||
|
@ -748,7 +748,7 @@ void vsh_translate(uint16_t version,
|
|||
/* pre-divide and output the generated W so we can do persepctive correct
|
||||
* interpolation manually. OpenGL can't, since we give it a W of 1 to work
|
||||
* around the perspective divide */
|
||||
qstring_append(body,
|
||||
mstring_append(body,
|
||||
" if (oPos.w == 0.0 || isinf(oPos.w)) {\n"
|
||||
" vtx.inv_w = 1.0;\n"
|
||||
" } else {\n"
|
||||
|
@ -756,7 +756,7 @@ void vsh_translate(uint16_t version,
|
|||
" }\n"
|
||||
);
|
||||
|
||||
qstring_append(body,
|
||||
mstring_append(body,
|
||||
/* the shaders leave the result in screen space, while
|
||||
* opengl expects it in clip space.
|
||||
* TODO: the pixel-center co-ordinate differences should handled
|
||||
|
@ -765,9 +765,9 @@ void vsh_translate(uint16_t version,
|
|||
" oPos.y = -2.0 * (oPos.y - surfaceSize.y * 0.5) / surfaceSize.y;\n"
|
||||
);
|
||||
if (z_perspective) {
|
||||
qstring_append(body, " oPos.z = oPos.w;\n");
|
||||
mstring_append(body, " oPos.z = oPos.w;\n");
|
||||
}
|
||||
qstring_append(body,
|
||||
mstring_append(body,
|
||||
/* Map the clip range into clip space so z is clipped correctly.
|
||||
* Note this makes the values in the depth buffer wrong. This should be
|
||||
* handled with gl_ClipDistance instead, but that has performance issues
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#define HW_NV2A_VSH_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "shaders_common.h"
|
||||
|
||||
enum VshLight {
|
||||
LIGHT_OFF,
|
||||
|
@ -134,7 +134,7 @@ void vsh_translate(uint16_t version,
|
|||
const uint32_t *tokens,
|
||||
unsigned int length,
|
||||
bool z_perspective,
|
||||
QString *header, QString *body);
|
||||
MString *header, MString *body);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue