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
|
// Blending
|
||||||
case PICA_REG_INDEX(framebuffer.output_merger.alphablend_enable):
|
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();
|
SyncBlendEnabled();
|
||||||
break;
|
break;
|
||||||
case PICA_REG_INDEX(framebuffer.output_merger.alpha_blending):
|
case PICA_REG_INDEX(framebuffer.output_merger.alpha_blending):
|
||||||
|
@ -1068,6 +1072,10 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
|
||||||
|
|
||||||
// Logic op
|
// Logic op
|
||||||
case PICA_REG_INDEX(framebuffer.output_merger.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();
|
SyncLogicOp();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1822,11 +1830,31 @@ void RasterizerOpenGL::SyncAlphaTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncLogicOp() {
|
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() {
|
void RasterizerOpenGL::SyncColorWriteMask() {
|
||||||
const auto& regs = Pica::g_state.regs;
|
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) {
|
auto IsColorWriteEnabled = [&](u32 value) {
|
||||||
return (regs.framebuffer.framebuffer.allow_color_write != 0 && value != 0) ? GL_TRUE
|
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;
|
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.
|
// Copy relevant tev stages fields.
|
||||||
// We don't sync const_color here because of the high variance, it is a
|
// We don't sync const_color here because of the high variance, it is a
|
||||||
// shader uniform instead.
|
// shader uniform instead.
|
||||||
|
@ -1568,6 +1579,32 @@ do {
|
||||||
out += "color = byteround(last_tex_env_out);\n";
|
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 += '}';
|
out += '}';
|
||||||
|
|
||||||
return {std::move(out)};
|
return {std::move(out)};
|
||||||
|
|
|
@ -61,6 +61,8 @@ struct PicaFSConfigState {
|
||||||
Pica::RasterizerRegs::DepthBuffering depthmap_enable;
|
Pica::RasterizerRegs::DepthBuffering depthmap_enable;
|
||||||
Pica::TexturingRegs::FogMode fog_mode;
|
Pica::TexturingRegs::FogMode fog_mode;
|
||||||
bool fog_flip;
|
bool fog_flip;
|
||||||
|
bool alphablend_enable;
|
||||||
|
Pica::FramebufferRegs::LogicOp logic_op;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -170,12 +170,19 @@ void OpenGLState::Apply() const {
|
||||||
if (blend.enabled != cur_state.blend.enabled) {
|
if (blend.enabled != cur_state.blend.enabled) {
|
||||||
if (blend.enabled) {
|
if (blend.enabled) {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glDisable(GL_COLOR_LOGIC_OP);
|
|
||||||
} else {
|
} else {
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GLES does not support glLogicOp
|
||||||
|
if (!GLES) {
|
||||||
|
if (blend.enabled) {
|
||||||
|
glDisable(GL_COLOR_LOGIC_OP);
|
||||||
|
} else {
|
||||||
glEnable(GL_COLOR_LOGIC_OP);
|
glEnable(GL_COLOR_LOGIC_OP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (blend.color.red != cur_state.blend.color.red ||
|
if (blend.color.red != cur_state.blend.color.red ||
|
||||||
blend.color.green != cur_state.blend.color.green ||
|
blend.color.green != cur_state.blend.color.green ||
|
||||||
|
@ -197,13 +204,11 @@ void OpenGLState::Apply() const {
|
||||||
glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
|
glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLES3 does not support glLogicOp
|
// GLES does not support glLogicOp
|
||||||
if (!GLES) {
|
if (!GLES) {
|
||||||
if (logic_op != cur_state.logic_op) {
|
if (logic_op != cur_state.logic_op) {
|
||||||
glLogicOp(logic_op);
|
glLogicOp(logic_op);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
LOG_TRACE(Render_OpenGL, "glLogicOps are unimplemented...");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Textures
|
// Textures
|
||||||
|
|
Loading…
Reference in a new issue