mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 04:21:04 +00:00
Add logic ops according to OpenGL ES 1.1 spec and 3dbrew.
This commit is contained in:
parent
40d1f9045a
commit
fba3ceb78f
@ -424,6 +424,27 @@ public:
|
|||||||
return x*x + y*y + z*z + w*w;
|
return x*x + y*y + z*z + w*w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Needed for logic ops
|
||||||
|
Vec4<decltype(~T{})> operator ~() const
|
||||||
|
{
|
||||||
|
return MakeVec(~x,~y,~z,~w);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4<decltype(T{}&T{})> operator &(const Vec4& other) const
|
||||||
|
{
|
||||||
|
return MakeVec(x&other.x, y&other.y, z&other.z, w&other.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4<decltype(T{}|T{})> operator |(const Vec4& other) const
|
||||||
|
{
|
||||||
|
return MakeVec(x|other.x, y|other.y, z|other.z, w|other.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4<decltype(T{}^T{})> operator ^(const Vec4& other) const
|
||||||
|
{
|
||||||
|
return MakeVec(x^other.x, y^other.y, z^other.z, w^other.w);
|
||||||
|
}
|
||||||
|
|
||||||
// Only implemented for T=float
|
// Only implemented for T=float
|
||||||
float Length() const;
|
float Length() const;
|
||||||
void SetLength(const float l);
|
void SetLength(const float l);
|
||||||
|
@ -374,7 +374,22 @@ struct Regs {
|
|||||||
|
|
||||||
union {
|
union {
|
||||||
enum Op {
|
enum Op {
|
||||||
|
Clear = 0,
|
||||||
|
And = 1,
|
||||||
|
AndReverse = 2,
|
||||||
|
Copy = 3,
|
||||||
Set = 4,
|
Set = 4,
|
||||||
|
CopyInverted = 5,
|
||||||
|
NoOp = 6,
|
||||||
|
Invert = 7,
|
||||||
|
Nand = 8,
|
||||||
|
Or = 9,
|
||||||
|
Nor = 10,
|
||||||
|
Xor = 11,
|
||||||
|
Equiv = 12,
|
||||||
|
AndInverted = 13,
|
||||||
|
OrReverse = 14,
|
||||||
|
OrInverted = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
BitField<0, 4, Op> op;
|
BitField<0, 4, Op> op;
|
||||||
|
@ -778,10 +778,89 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0,
|
|||||||
blend_output = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_rgb);
|
blend_output = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_rgb);
|
||||||
blend_output.a() = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_a).a();
|
blend_output.a() = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_a).a();
|
||||||
} else {
|
} else {
|
||||||
LOG_CRITICAL(HW_GPU, "logic op: %x", registers.output_merger.logic_op);
|
auto params = registers.output_merger.logic_op;
|
||||||
|
|
||||||
|
using LogicOp = decltype(params)::Op;
|
||||||
|
|
||||||
|
auto EvaluateLogicOp = [&](const Math::Vec4<u8>& src, const Math::Vec4<u8>& dest
|
||||||
|
LogicOp op) -> Math::Vec4<u8> {
|
||||||
|
Math::Vec4<u8> result;
|
||||||
|
|
||||||
|
switch(op) {
|
||||||
|
case LogicOp::Clear:
|
||||||
|
result = Math::Vec4<u8>(0,0,0,0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::And:
|
||||||
|
result = src & dest;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::AndReverse:
|
||||||
|
result = src & ~dest;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::Copy:
|
||||||
|
result = src;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::Set:
|
||||||
|
result = Math::Vec4<u8>(1,1,1,1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::CopyInverted:
|
||||||
|
result = ~src;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::NoOp:
|
||||||
|
result = dest;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::Invert:
|
||||||
|
result = ~dest;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::Nand:
|
||||||
|
result = ~(src & dest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::Or:
|
||||||
|
result = src | dest;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::Nor:
|
||||||
|
result = ~(src | dest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::Xor:
|
||||||
|
result = src ^ dest;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::Equiv:
|
||||||
|
result = ~(src ^ dest);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::AndInverted:
|
||||||
|
result = ~src & dest;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::OrReverse:
|
||||||
|
result = src | ~dest;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LogicOp::OrInverted:
|
||||||
|
result = ~src | dest;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_CRITICAL(HW_GPU, "Unknown logic op %x", op);
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
blend_output = EvaluateLogicOp(combiner_output, dest, params.op);
|
||||||
|
}
|
||||||
|
|
||||||
const Math::Vec4<u8> result = {
|
const Math::Vec4<u8> result = {
|
||||||
registers.output_merger.red_enable ? blend_output.r() : dest.r(),
|
registers.output_merger.red_enable ? blend_output.r() : dest.r(),
|
||||||
registers.output_merger.green_enable ? blend_output.g() : dest.g(),
|
registers.output_merger.green_enable ? blend_output.g() : dest.g(),
|
||||||
|
Loading…
Reference in New Issue
Block a user