mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	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,10 +170,17 @@ 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); | ||||
|             glEnable(GL_COLOR_LOGIC_OP); | ||||
|         } | ||||
| 
 | ||||
|         // GLES does not support glLogicOp
 | ||||
|         if (!GLES) { | ||||
|             if (blend.enabled) { | ||||
|                 glDisable(GL_COLOR_LOGIC_OP); | ||||
|             } else { | ||||
|                 glEnable(GL_COLOR_LOGIC_OP); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue