android: renderer_opengl: Partially implement glLogicOp on GLES.
This commit is contained in:
parent
853acce6c5
commit
a941547c1c
4 changed files with 78 additions and 6 deletions
|
@ -948,6 +948,10 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
|
|||
|
||||
// Blending
|
||||
case PICA_REG_INDEX(framebuffer.output_merger.alphablend_enable):
|
||||
if (GLES) {
|
||||
// With GLES, we need this in the fragment shader to emulate logic operations
|
||||
shader_dirty = true;
|
||||
}
|
||||
SyncBlendEnabled();
|
||||
break;
|
||||
case PICA_REG_INDEX(framebuffer.output_merger.alpha_blending):
|
||||
|
@ -1068,6 +1072,10 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
|
|||
|
||||
// Logic op
|
||||
case PICA_REG_INDEX(framebuffer.output_merger.logic_op):
|
||||
if (GLES) {
|
||||
// With GLES, we need this in the fragment shader to emulate logic operations
|
||||
shader_dirty = true;
|
||||
}
|
||||
SyncLogicOp();
|
||||
break;
|
||||
|
||||
|
@ -1822,11 +1830,31 @@ void RasterizerOpenGL::SyncAlphaTest() {
|
|||
}
|
||||
|
||||
void RasterizerOpenGL::SyncLogicOp() {
|
||||
state.logic_op = PicaToGL::LogicOp(Pica::g_state.regs.framebuffer.output_merger.logic_op);
|
||||
const auto& regs = Pica::g_state.regs;
|
||||
state.logic_op = PicaToGL::LogicOp(regs.framebuffer.output_merger.logic_op);
|
||||
|
||||
if (GLES) {
|
||||
if (!regs.framebuffer.output_merger.alphablend_enable) {
|
||||
if (regs.framebuffer.output_merger.logic_op == Pica::FramebufferRegs::LogicOp::NoOp) {
|
||||
// Color output is disabled by logic operation. We use color write mask to skip
|
||||
// color but allow depth write.
|
||||
state.color_mask = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::SyncColorWriteMask() {
|
||||
const auto& regs = Pica::g_state.regs;
|
||||
if (GLES) {
|
||||
if (!regs.framebuffer.output_merger.alphablend_enable) {
|
||||
if (regs.framebuffer.output_merger.logic_op == Pica::FramebufferRegs::LogicOp::NoOp) {
|
||||
// Color output is disabled by logic operation. We use color write mask to skip
|
||||
// color but allow depth write. Return early to avoid overwriting this.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto IsColorWriteEnabled = [&](u32 value) {
|
||||
return (regs.framebuffer.framebuffer.allow_color_write != 0 && value != 0) ? GL_TRUE
|
||||
|
|
|
@ -127,6 +127,17 @@ PicaFSConfig PicaFSConfig::BuildFromRegs(const Pica::Regs& regs) {
|
|||
|
||||
state.texture2_use_coord1 = regs.texturing.main_config.texture2_use_coord1 != 0;
|
||||
|
||||
if (GLES) {
|
||||
// With GLES, we need this in the fragment shader to emulate logic operations
|
||||
state.alphablend_enable =
|
||||
Pica::g_state.regs.framebuffer.output_merger.alphablend_enable == 1;
|
||||
state.logic_op = regs.framebuffer.output_merger.logic_op;
|
||||
} else {
|
||||
// We don't need these otherwise, reset them to avoid unnecessary shader generation
|
||||
state.alphablend_enable = {};
|
||||
state.logic_op = {};
|
||||
}
|
||||
|
||||
// Copy relevant tev stages fields.
|
||||
// We don't sync const_color here because of the high variance, it is a
|
||||
// shader uniform instead.
|
||||
|
@ -1568,6 +1579,32 @@ do {
|
|||
out += "color = byteround(last_tex_env_out);\n";
|
||||
}
|
||||
|
||||
if (GLES) {
|
||||
if (!state.alphablend_enable) {
|
||||
switch (state.logic_op) {
|
||||
case FramebufferRegs::LogicOp::Clear:
|
||||
out += "color = vec4(0);\n";
|
||||
break;
|
||||
case FramebufferRegs::LogicOp::Set:
|
||||
out += "color = vec4(1);\n";
|
||||
break;
|
||||
case FramebufferRegs::LogicOp::Copy:
|
||||
// Take the color output as-is
|
||||
break;
|
||||
case FramebufferRegs::LogicOp::CopyInverted:
|
||||
out += "color = ~color;\n";
|
||||
break;
|
||||
case FramebufferRegs::LogicOp::NoOp:
|
||||
// We need to discard the color, but not necessarily the depth. This is not possible
|
||||
// with fragment shader alone, so we emulate this behavior on GLES with glColorMask.
|
||||
break;
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unhandled logic_op {:x}", static_cast<int>(state.logic_op));
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out += '}';
|
||||
|
||||
return {std::move(out)};
|
||||
|
|
|
@ -61,6 +61,8 @@ struct PicaFSConfigState {
|
|||
Pica::RasterizerRegs::DepthBuffering depthmap_enable;
|
||||
Pica::TexturingRegs::FogMode fog_mode;
|
||||
bool fog_flip;
|
||||
bool alphablend_enable;
|
||||
Pica::FramebufferRegs::LogicOp logic_op;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
|
|
|
@ -170,12 +170,19 @@ void OpenGLState::Apply() const {
|
|||
if (blend.enabled != cur_state.blend.enabled) {
|
||||
if (blend.enabled) {
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_COLOR_LOGIC_OP);
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
// GLES does not support glLogicOp
|
||||
if (!GLES) {
|
||||
if (blend.enabled) {
|
||||
glDisable(GL_COLOR_LOGIC_OP);
|
||||
} else {
|
||||
glEnable(GL_COLOR_LOGIC_OP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (blend.color.red != cur_state.blend.color.red ||
|
||||
blend.color.green != cur_state.blend.color.green ||
|
||||
|
@ -197,13 +204,11 @@ void OpenGLState::Apply() const {
|
|||
glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
|
||||
}
|
||||
|
||||
// GLES3 does not support glLogicOp
|
||||
// GLES does not support glLogicOp
|
||||
if (!GLES) {
|
||||
if (logic_op != cur_state.logic_op) {
|
||||
glLogicOp(logic_op);
|
||||
}
|
||||
} else {
|
||||
LOG_TRACE(Render_OpenGL, "glLogicOps are unimplemented...");
|
||||
}
|
||||
|
||||
// Textures
|
||||
|
|
Loading…
Reference in a new issue