OpenGL: Respect color-read allow register
This commit is contained in:
parent
eb77c1ed3b
commit
dad051f55f
1 changed files with 88 additions and 5 deletions
|
@ -308,6 +308,12 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
|
|||
SyncColorWriteMask();
|
||||
break;
|
||||
|
||||
// Color read mask
|
||||
case PICA_REG_INDEX(framebuffer.allow_color_read):
|
||||
SyncLogicOp();
|
||||
SyncBlendFuncs();
|
||||
break;
|
||||
|
||||
// Logic op
|
||||
case PICA_REG_INDEX(output_merger.logic_op):
|
||||
SyncLogicOp();
|
||||
|
@ -883,10 +889,33 @@ void RasterizerOpenGL::SyncBlendEnabled() {
|
|||
|
||||
void RasterizerOpenGL::SyncBlendFuncs() {
|
||||
const auto& regs = Pica::g_state.regs;
|
||||
state.blend.src_rgb_func = PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_source_rgb);
|
||||
state.blend.dst_rgb_func = PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_dest_rgb);
|
||||
state.blend.src_a_func = PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_source_a);
|
||||
state.blend.dst_a_func = PicaToGL::BlendFunc(regs.output_merger.alpha_blending.factor_dest_a);
|
||||
|
||||
// This function pretends the destination read was 0x00 if the reads are not allowed
|
||||
auto BlendAllowedFunc = [&](bool dest, Pica::Regs::BlendFactor factor) -> GLenum {
|
||||
|
||||
if (regs.framebuffer.allow_color_read == 0x0) {
|
||||
|
||||
// Destination would only read zero, so we can multiply by ZERO in blend func
|
||||
if (dest)
|
||||
return GL_ZERO;
|
||||
|
||||
if (factor == Pica::Regs::BlendFactor::DestColor ||
|
||||
factor == Pica::Regs::BlendFactor::DestAlpha)
|
||||
return GL_ZERO;
|
||||
|
||||
if (factor == Pica::Regs::BlendFactor::OneMinusDestColor ||
|
||||
factor == Pica::Regs::BlendFactor::OneMinusDestAlpha)
|
||||
return GL_ONE;
|
||||
|
||||
}
|
||||
|
||||
return PicaToGL::BlendFunc(factor);
|
||||
};
|
||||
|
||||
state.blend.src_rgb_func = BlendAllowedFunc(false, regs.output_merger.alpha_blending.factor_source_rgb);
|
||||
state.blend.dst_rgb_func = BlendAllowedFunc(true, regs.output_merger.alpha_blending.factor_dest_rgb);
|
||||
state.blend.src_a_func = BlendAllowedFunc(false, regs.output_merger.alpha_blending.factor_source_a);
|
||||
state.blend.dst_a_func = BlendAllowedFunc(true, regs.output_merger.alpha_blending.factor_dest_a);
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::SyncBlendColor() {
|
||||
|
@ -906,7 +935,61 @@ void RasterizerOpenGL::SyncAlphaTest() {
|
|||
}
|
||||
|
||||
void RasterizerOpenGL::SyncLogicOp() {
|
||||
state.logic_op = PicaToGL::LogicOp(Pica::g_state.regs.output_merger.logic_op);
|
||||
const auto& regs = Pica::g_state.regs;
|
||||
|
||||
if (regs.framebuffer.allow_color_read == 0x0) {
|
||||
|
||||
// Pretend that the destination reads always return 0
|
||||
switch (regs.output_merger.logic_op) {
|
||||
|
||||
// Always 0
|
||||
case Pica::Regs::LogicOp::Clear:
|
||||
case Pica::Regs::LogicOp::And:
|
||||
case Pica::Regs::LogicOp::AndInverted:
|
||||
state.logic_op = GL_CLEAR;
|
||||
break;
|
||||
|
||||
// Always s
|
||||
case Pica::Regs::LogicOp::AndReverse:
|
||||
case Pica::Regs::LogicOp::Copy:
|
||||
case Pica::Regs::LogicOp::Or:
|
||||
case Pica::Regs::LogicOp::Xor:
|
||||
state.logic_op = GL_COPY;
|
||||
break;
|
||||
|
||||
// Always 1
|
||||
case Pica::Regs::LogicOp::Set:
|
||||
case Pica::Regs::LogicOp::Invert:
|
||||
case Pica::Regs::LogicOp::Nand:
|
||||
case Pica::Regs::LogicOp::OrReverse:
|
||||
state.logic_op = GL_SET;
|
||||
break;
|
||||
|
||||
// Always ~s
|
||||
case Pica::Regs::LogicOp::CopyInverted:
|
||||
case Pica::Regs::LogicOp::Nor:
|
||||
case Pica::Regs::LogicOp::Equiv:
|
||||
case Pica::Regs::LogicOp::OrInverted:
|
||||
state.logic_op = GL_COPY_INVERTED;
|
||||
break;
|
||||
|
||||
// FIXME: Decide for one of those:
|
||||
//a. NoOp means reading zero, writing back zero
|
||||
//b. NoOp means not touching the framebuffer
|
||||
case Pica::Regs::LogicOp::NoOp:
|
||||
state.logic_op = GL_CLEAR; // a
|
||||
state.logic_op = GL_NOOP; // b
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_CRITICAL(Render_OpenGL, "Unknown logic op %d", regs.output_merger.logic_op);
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
state.logic_op = PicaToGL::LogicOp(regs.output_merger.logic_op);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::SyncColorWriteMask() {
|
||||
|
|
Loading…
Reference in a new issue