From c4ed0b16b1c22658fd7e388a3244f472609622a6 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Wed, 22 Aug 2018 00:17:54 -0400
Subject: [PATCH] gl_state: Update to handle stencil front/back face
 separately.

---
 src/video_core/renderer_opengl/gl_state.cpp | 53 +++++++++++----------
 src/video_core/renderer_opengl/gl_state.h   | 18 +++----
 2 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index e1a887d67..60a4defd1 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -27,13 +27,17 @@ OpenGLState::OpenGLState() {
     color_mask.alpha_enabled = GL_TRUE;
 
     stencil.test_enabled = false;
-    stencil.test_func = GL_ALWAYS;
-    stencil.test_ref = 0;
-    stencil.test_mask = 0xFF;
-    stencil.write_mask = 0xFF;
-    stencil.action_depth_fail = GL_KEEP;
-    stencil.action_depth_pass = GL_KEEP;
-    stencil.action_stencil_fail = GL_KEEP;
+    auto reset_stencil = [](auto& config) {
+        config.test_func = GL_ALWAYS;
+        config.test_ref = 0;
+        config.test_mask = 0xFFFFFFFF;
+        config.write_mask = 0xFFFFFFFF;
+        config.action_depth_fail = GL_KEEP;
+        config.action_depth_pass = GL_KEEP;
+        config.action_stencil_fail = GL_KEEP;
+    };
+    reset_stencil(stencil.front);
+    reset_stencil(stencil.back);
 
     blend.enabled = true;
     blend.rgb_equation = GL_FUNC_ADD;
@@ -129,24 +133,23 @@ void OpenGLState::Apply() const {
             glDisable(GL_STENCIL_TEST);
         }
     }
-
-    if (stencil.test_func != cur_state.stencil.test_func ||
-        stencil.test_ref != cur_state.stencil.test_ref ||
-        stencil.test_mask != cur_state.stencil.test_mask) {
-        glStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask);
-    }
-
-    if (stencil.action_depth_fail != cur_state.stencil.action_depth_fail ||
-        stencil.action_depth_pass != cur_state.stencil.action_depth_pass ||
-        stencil.action_stencil_fail != cur_state.stencil.action_stencil_fail) {
-        glStencilOp(stencil.action_stencil_fail, stencil.action_depth_fail,
-                    stencil.action_depth_pass);
-    }
-
-    // Stencil mask
-    if (stencil.write_mask != cur_state.stencil.write_mask) {
-        glStencilMask(stencil.write_mask);
-    }
+    auto config_stencil = [](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);
+        }
+    };
+    config_stencil(GL_FRONT, stencil.front, cur_state.stencil.front);
+    config_stencil(GL_BACK, stencil.back, cur_state.stencil.back);
 
     // Blending
     if (blend.enabled != cur_state.blend.enabled) {
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 22b0b1e41..46e96a97d 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -58,14 +58,16 @@ public:
     } color_mask; // GL_COLOR_WRITEMASK
 
     struct {
-        bool test_enabled;          // GL_STENCIL_TEST
-        GLenum test_func;           // GL_STENCIL_FUNC
-        GLint test_ref;             // GL_STENCIL_REF
-        GLuint test_mask;           // GL_STENCIL_VALUE_MASK
-        GLuint write_mask;          // GL_STENCIL_WRITEMASK
-        GLenum action_stencil_fail; // GL_STENCIL_FAIL
-        GLenum action_depth_fail;   // GL_STENCIL_PASS_DEPTH_FAIL
-        GLenum action_depth_pass;   // GL_STENCIL_PASS_DEPTH_PASS
+        bool test_enabled; // GL_STENCIL_TEST
+        struct {
+            GLenum test_func;           // GL_STENCIL_FUNC
+            GLint test_ref;             // GL_STENCIL_REF
+            GLuint test_mask;           // GL_STENCIL_VALUE_MASK
+            GLuint write_mask;          // GL_STENCIL_WRITEMASK
+            GLenum action_stencil_fail; // GL_STENCIL_FAIL
+            GLenum action_depth_fail;   // GL_STENCIL_PASS_DEPTH_FAIL
+            GLenum action_depth_pass;   // GL_STENCIL_PASS_DEPTH_PASS
+        } front, back;
     } stencil;
 
     struct {