mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40: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
 |     // 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,10 +170,17 @@ 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); | ||||||
|             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); |         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…
	
	Add table
		Add a link
		
	
		Reference in a new issue