mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-10-26 13:42:48 -05:00 
			
		
		
		
	gl_state: Synchronize gl_state even when state is disabled
There are some potential edge cases where gl_state may fail to track the state if a related state changes while the toggle is disabled or it didn't change. This addresses that.
This commit is contained in:
		| @@ -11,7 +11,9 @@ | ||||
| namespace OpenGL { | ||||
|  | ||||
| OpenGLState OpenGLState::cur_state; | ||||
|  | ||||
| bool OpenGLState::s_rgb_used; | ||||
|  | ||||
| OpenGLState::OpenGLState() { | ||||
|     // These all match default OpenGL values | ||||
|     geometry_shaders.enabled = false; | ||||
| @@ -112,7 +114,6 @@ void OpenGLState::ApplyDefaultState() { | ||||
| } | ||||
|  | ||||
| void OpenGLState::ApplySRgb() const { | ||||
|     // sRGB | ||||
|     if (framebuffer_srgb.enabled != cur_state.framebuffer_srgb.enabled) { | ||||
|         if (framebuffer_srgb.enabled) { | ||||
|             // Track if sRGB is used | ||||
| @@ -125,23 +126,20 @@ void OpenGLState::ApplySRgb() const { | ||||
| } | ||||
|  | ||||
| void OpenGLState::ApplyCulling() const { | ||||
|     // Culling | ||||
|     const bool cull_changed = cull.enabled != cur_state.cull.enabled; | ||||
|     if (cull_changed) { | ||||
|     if (cull.enabled != cur_state.cull.enabled) { | ||||
|         if (cull.enabled) { | ||||
|             glEnable(GL_CULL_FACE); | ||||
|         } else { | ||||
|             glDisable(GL_CULL_FACE); | ||||
|         } | ||||
|     } | ||||
|     if (cull.enabled) { | ||||
|         if (cull_changed || cull.mode != cur_state.cull.mode) { | ||||
|             glCullFace(cull.mode); | ||||
|         } | ||||
|  | ||||
|         if (cull_changed || cull.front_face != cur_state.cull.front_face) { | ||||
|             glFrontFace(cull.front_face); | ||||
|         } | ||||
|     if (cull.mode != cur_state.cull.mode) { | ||||
|         glCullFace(cull.mode); | ||||
|     } | ||||
|  | ||||
|     if (cull.front_face != cur_state.cull.front_face) { | ||||
|         glFrontFace(cull.front_face); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -172,72 +170,63 @@ void OpenGLState::ApplyColorMask() const { | ||||
| } | ||||
|  | ||||
| void OpenGLState::ApplyDepth() const { | ||||
|     // Depth test | ||||
|     const bool depth_test_changed = depth.test_enabled != cur_state.depth.test_enabled; | ||||
|     if (depth_test_changed) { | ||||
|     if (depth.test_enabled != cur_state.depth.test_enabled) { | ||||
|         if (depth.test_enabled) { | ||||
|             glEnable(GL_DEPTH_TEST); | ||||
|         } else { | ||||
|             glDisable(GL_DEPTH_TEST); | ||||
|         } | ||||
|     } | ||||
|     if (depth.test_enabled && | ||||
|         (depth_test_changed || depth.test_func != cur_state.depth.test_func)) { | ||||
|  | ||||
|     if (depth.test_func != cur_state.depth.test_func) { | ||||
|         glDepthFunc(depth.test_func); | ||||
|     } | ||||
|     // Depth mask | ||||
|  | ||||
|     if (depth.write_mask != cur_state.depth.write_mask) { | ||||
|         glDepthMask(depth.write_mask); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void OpenGLState::ApplyPrimitiveRestart() const { | ||||
|     const bool primitive_restart_changed = | ||||
|         primitive_restart.enabled != cur_state.primitive_restart.enabled; | ||||
|     if (primitive_restart_changed) { | ||||
|     if (primitive_restart.enabled != cur_state.primitive_restart.enabled) { | ||||
|         if (primitive_restart.enabled) { | ||||
|             glEnable(GL_PRIMITIVE_RESTART); | ||||
|         } else { | ||||
|             glDisable(GL_PRIMITIVE_RESTART); | ||||
|         } | ||||
|     } | ||||
|     if (primitive_restart_changed || | ||||
|         (primitive_restart.enabled && | ||||
|          primitive_restart.index != cur_state.primitive_restart.index)) { | ||||
|  | ||||
|     if (primitive_restart.index != cur_state.primitive_restart.index) { | ||||
|         glPrimitiveRestartIndex(primitive_restart.index); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void OpenGLState::ApplyStencilTest() const { | ||||
|     const bool stencil_test_changed = stencil.test_enabled != cur_state.stencil.test_enabled; | ||||
|     if (stencil_test_changed) { | ||||
|     if (stencil.test_enabled != cur_state.stencil.test_enabled) { | ||||
|         if (stencil.test_enabled) { | ||||
|             glEnable(GL_STENCIL_TEST); | ||||
|         } else { | ||||
|             glDisable(GL_STENCIL_TEST); | ||||
|         } | ||||
|     } | ||||
|     if (stencil.test_enabled) { | ||||
|         auto config_stencil = [stencil_test_changed](GLenum face, const auto& config, | ||||
|                                                      const auto& prev_config) { | ||||
|             if (stencil_test_changed || config.test_func != prev_config.test_func || | ||||
|                 config.test_ref != prev_config.test_ref || | ||||
|                 config.test_mask != prev_config.test_mask) { | ||||
|                 glStencilFuncSeparate(face, config.test_func, config.test_ref, config.test_mask); | ||||
|             } | ||||
|             if (stencil_test_changed || config.action_depth_fail != prev_config.action_depth_fail || | ||||
|                 config.action_depth_pass != prev_config.action_depth_pass || | ||||
|                 config.action_stencil_fail != prev_config.action_stencil_fail) { | ||||
|                 glStencilOpSeparate(face, config.action_stencil_fail, config.action_depth_fail, | ||||
|                                     config.action_depth_pass); | ||||
|             } | ||||
|             if (config.write_mask != prev_config.write_mask) { | ||||
|                 glStencilMaskSeparate(face, config.write_mask); | ||||
|             } | ||||
|         }; | ||||
|         config_stencil(GL_FRONT, stencil.front, cur_state.stencil.front); | ||||
|         config_stencil(GL_BACK, stencil.back, cur_state.stencil.back); | ||||
|     } | ||||
|  | ||||
|     const auto ConfigStencil = [](GLenum face, const auto& config, const auto& prev_config) { | ||||
|         if (config.test_func != prev_config.test_func || config.test_ref != prev_config.test_ref || | ||||
|             config.test_mask != prev_config.test_mask) { | ||||
|             glStencilFuncSeparate(face, config.test_func, config.test_ref, config.test_mask); | ||||
|         } | ||||
|         if (config.action_depth_fail != prev_config.action_depth_fail || | ||||
|             config.action_depth_pass != prev_config.action_depth_pass || | ||||
|             config.action_stencil_fail != prev_config.action_stencil_fail) { | ||||
|             glStencilOpSeparate(face, config.action_stencil_fail, config.action_depth_fail, | ||||
|                                 config.action_depth_pass); | ||||
|         } | ||||
|         if (config.write_mask != prev_config.write_mask) { | ||||
|             glStencilMaskSeparate(face, config.write_mask); | ||||
|         } | ||||
|     }; | ||||
|     ConfigStencil(GL_FRONT, stencil.front, cur_state.stencil.front); | ||||
|     ConfigStencil(GL_BACK, stencil.back, cur_state.stencil.back); | ||||
| } | ||||
| // Viewport does not affects glClearBuffer so emulate viewport using scissor test | ||||
| void OpenGLState::EmulateViewportWithScissor() { | ||||
| @@ -278,19 +267,18 @@ void OpenGLState::ApplyViewport() const { | ||||
|                 updated.depth_range_far != current.depth_range_far) { | ||||
|                 glDepthRangeIndexed(i, updated.depth_range_near, updated.depth_range_far); | ||||
|             } | ||||
|             const bool scissor_changed = updated.scissor.enabled != current.scissor.enabled; | ||||
|             if (scissor_changed) { | ||||
|  | ||||
|             if (updated.scissor.enabled != current.scissor.enabled) { | ||||
|                 if (updated.scissor.enabled) { | ||||
|                     glEnablei(GL_SCISSOR_TEST, i); | ||||
|                 } else { | ||||
|                     glDisablei(GL_SCISSOR_TEST, i); | ||||
|                 } | ||||
|             } | ||||
|             if (updated.scissor.enabled && | ||||
|                 (scissor_changed || updated.scissor.x != current.scissor.x || | ||||
|                  updated.scissor.y != current.scissor.y || | ||||
|                  updated.scissor.width != current.scissor.width || | ||||
|                  updated.scissor.height != current.scissor.height)) { | ||||
|  | ||||
|             if (updated.scissor.x != current.scissor.x || updated.scissor.y != current.scissor.y || | ||||
|                 updated.scissor.width != current.scissor.width || | ||||
|                 updated.scissor.height != current.scissor.height) { | ||||
|                 glScissorIndexed(i, updated.scissor.x, updated.scissor.y, updated.scissor.width, | ||||
|                                  updated.scissor.height); | ||||
|             } | ||||
| @@ -302,22 +290,23 @@ void OpenGLState::ApplyViewport() const { | ||||
|             updated.height != current.height) { | ||||
|             glViewport(updated.x, updated.y, updated.width, updated.height); | ||||
|         } | ||||
|  | ||||
|         if (updated.depth_range_near != current.depth_range_near || | ||||
|             updated.depth_range_far != current.depth_range_far) { | ||||
|             glDepthRange(updated.depth_range_near, updated.depth_range_far); | ||||
|         } | ||||
|         const bool scissor_changed = updated.scissor.enabled != current.scissor.enabled; | ||||
|         if (scissor_changed) { | ||||
|  | ||||
|         if (updated.scissor.enabled != current.scissor.enabled) { | ||||
|             if (updated.scissor.enabled) { | ||||
|                 glEnable(GL_SCISSOR_TEST); | ||||
|             } else { | ||||
|                 glDisable(GL_SCISSOR_TEST); | ||||
|             } | ||||
|         } | ||||
|         if (updated.scissor.enabled && (scissor_changed || updated.scissor.x != current.scissor.x || | ||||
|                                         updated.scissor.y != current.scissor.y || | ||||
|                                         updated.scissor.width != current.scissor.width || | ||||
|                                         updated.scissor.height != current.scissor.height)) { | ||||
|  | ||||
|         if (updated.scissor.x != current.scissor.x || updated.scissor.y != current.scissor.y || | ||||
|             updated.scissor.width != current.scissor.width || | ||||
|             updated.scissor.height != current.scissor.height) { | ||||
|             glScissor(updated.scissor.x, updated.scissor.y, updated.scissor.width, | ||||
|                       updated.scissor.height); | ||||
|         } | ||||
| @@ -327,8 +316,7 @@ void OpenGLState::ApplyViewport() const { | ||||
| void OpenGLState::ApplyGlobalBlending() const { | ||||
|     const Blend& current = cur_state.blend[0]; | ||||
|     const Blend& updated = blend[0]; | ||||
|     const bool blend_changed = updated.enabled != current.enabled; | ||||
|     if (blend_changed) { | ||||
|     if (updated.enabled != current.enabled) { | ||||
|         if (updated.enabled) { | ||||
|             glEnable(GL_BLEND); | ||||
|         } else { | ||||
| @@ -338,15 +326,14 @@ void OpenGLState::ApplyGlobalBlending() const { | ||||
|     if (!updated.enabled) { | ||||
|         return; | ||||
|     } | ||||
|     if (blend_changed || updated.src_rgb_func != current.src_rgb_func || | ||||
|     if (updated.src_rgb_func != current.src_rgb_func || | ||||
|         updated.dst_rgb_func != current.dst_rgb_func || updated.src_a_func != current.src_a_func || | ||||
|         updated.dst_a_func != current.dst_a_func) { | ||||
|         glBlendFuncSeparate(updated.src_rgb_func, updated.dst_rgb_func, updated.src_a_func, | ||||
|                             updated.dst_a_func); | ||||
|     } | ||||
|  | ||||
|     if (blend_changed || updated.rgb_equation != current.rgb_equation || | ||||
|         updated.a_equation != current.a_equation) { | ||||
|     if (updated.rgb_equation != current.rgb_equation || updated.a_equation != current.a_equation) { | ||||
|         glBlendEquationSeparate(updated.rgb_equation, updated.a_equation); | ||||
|     } | ||||
| } | ||||
| @@ -354,26 +341,22 @@ void OpenGLState::ApplyGlobalBlending() const { | ||||
| void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) const { | ||||
|     const Blend& updated = blend[target]; | ||||
|     const Blend& current = cur_state.blend[target]; | ||||
|     const bool blend_changed = updated.enabled != current.enabled || force; | ||||
|     if (blend_changed) { | ||||
|     if (updated.enabled != current.enabled || force) { | ||||
|         if (updated.enabled) { | ||||
|             glEnablei(GL_BLEND, static_cast<GLuint>(target)); | ||||
|         } else { | ||||
|             glDisablei(GL_BLEND, static_cast<GLuint>(target)); | ||||
|         } | ||||
|     } | ||||
|     if (!updated.enabled) { | ||||
|         return; | ||||
|     } | ||||
|     if (blend_changed || updated.src_rgb_func != current.src_rgb_func || | ||||
|  | ||||
|     if (updated.src_rgb_func != current.src_rgb_func || | ||||
|         updated.dst_rgb_func != current.dst_rgb_func || updated.src_a_func != current.src_a_func || | ||||
|         updated.dst_a_func != current.dst_a_func) { | ||||
|         glBlendFuncSeparatei(static_cast<GLuint>(target), updated.src_rgb_func, | ||||
|                              updated.dst_rgb_func, updated.src_a_func, updated.dst_a_func); | ||||
|     } | ||||
|  | ||||
|     if (blend_changed || updated.rgb_equation != current.rgb_equation || | ||||
|         updated.a_equation != current.a_equation) { | ||||
|     if (updated.rgb_equation != current.rgb_equation || updated.a_equation != current.a_equation) { | ||||
|         glBlendEquationSeparatei(static_cast<GLuint>(target), updated.rgb_equation, | ||||
|                                  updated.a_equation); | ||||
|     } | ||||
| @@ -397,8 +380,7 @@ void OpenGLState::ApplyBlending() const { | ||||
| } | ||||
|  | ||||
| void OpenGLState::ApplyLogicOp() const { | ||||
|     const bool logic_op_changed = logic_op.enabled != cur_state.logic_op.enabled; | ||||
|     if (logic_op_changed) { | ||||
|     if (logic_op.enabled != cur_state.logic_op.enabled) { | ||||
|         if (logic_op.enabled) { | ||||
|             glEnable(GL_COLOR_LOGIC_OP); | ||||
|         } else { | ||||
| @@ -406,14 +388,12 @@ void OpenGLState::ApplyLogicOp() const { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (logic_op.enabled && | ||||
|         (logic_op_changed || logic_op.operation != cur_state.logic_op.operation)) { | ||||
|     if (logic_op.operation != cur_state.logic_op.operation) { | ||||
|         glLogicOp(logic_op.operation); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void OpenGLState::ApplyPolygonOffset() const { | ||||
|  | ||||
|     const bool fill_enable_changed = | ||||
|         polygon_offset.fill_enable != cur_state.polygon_offset.fill_enable; | ||||
|     const bool line_enable_changed = | ||||
| @@ -448,9 +428,7 @@ void OpenGLState::ApplyPolygonOffset() const { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if ((polygon_offset.fill_enable || polygon_offset.line_enable || polygon_offset.point_enable) && | ||||
|         (factor_changed || units_changed || clamp_changed)) { | ||||
|  | ||||
|     if (factor_changed || units_changed || clamp_changed) { | ||||
|         if (GLAD_GL_EXT_polygon_offset_clamp && polygon_offset.clamp != 0) { | ||||
|             glPolygonOffsetClamp(polygon_offset.factor, polygon_offset.units, polygon_offset.clamp); | ||||
|         } else { | ||||
| @@ -528,9 +506,9 @@ void OpenGLState::ApplyDepthClamp() const { | ||||
|         depth_clamp.near_plane == cur_state.depth_clamp.near_plane) { | ||||
|         return; | ||||
|     } | ||||
|     if (depth_clamp.far_plane != depth_clamp.near_plane) { | ||||
|         UNIMPLEMENTED_MSG("Unimplemented Depth Clamp Separation!"); | ||||
|     } | ||||
|     UNIMPLEMENTED_IF_MSG(depth_clamp.far_plane != depth_clamp.near_plane, | ||||
|                          "Unimplemented Depth Clamp Separation!"); | ||||
|  | ||||
|     if (depth_clamp.far_plane || depth_clamp.near_plane) { | ||||
|         glEnable(GL_DEPTH_CLAMP); | ||||
|     } else { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ReinUsesLisp
					ReinUsesLisp