Make glEnable/Disable entry points lockless

These entry points only set context-local state and thus don't require
locking.

Bug: angleproject:8224
Change-Id: Id4eab729115bd75f82e1ec7a27355c821a7c4320
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4661697
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Igor Nazarov <i.nazarov@samsung.com>
Reviewed-by: Charlie Lao <cclao@google.com>
diff --git a/scripts/code_generation_hashes/GL_EGL_entry_points.json b/scripts/code_generation_hashes/GL_EGL_entry_points.json
index df34d1c..4202cbe 100644
--- a/scripts/code_generation_hashes/GL_EGL_entry_points.json
+++ b/scripts/code_generation_hashes/GL_EGL_entry_points.json
@@ -6,7 +6,7 @@
   "scripts/entry_point_packed_gl_enums.json":
     "1c6b036918aabb9822a638fbf33f87f4",
   "scripts/generate_entry_points.py":
-    "c7997b2073a073dfa430214bef5714e2",
+    "f7af666b188708357306a1e34c46ae3f",
   "scripts/gl_angle_ext.xml":
     "49a0bf469d6f44c532098ef3a9fd087f",
   "scripts/registry_xml.py":
@@ -30,13 +30,13 @@
   "src/libANGLE/Context_gles_1_0_autogen.h":
     "e20ac775a0d01180d35d0477198e093c",
   "src/libANGLE/Context_gles_2_0_autogen.h":
-    "0493c2638599dcdc39c44bc84f1e4525",
+    "cc1f7fdce7d23dc62b0943b67bbdf6d3",
   "src/libANGLE/Context_gles_3_0_autogen.h":
     "3a4b261be12c9eb28c38da34c008a3f7",
   "src/libANGLE/Context_gles_3_1_autogen.h":
     "e26ffdad1be7d4a4aabecf7bfb40bf3f",
   "src/libANGLE/Context_gles_3_2_autogen.h":
-    "546e60fc99911ea3a5b955415b81dd73",
+    "8c09337af5c193b0808d49ec343ceeeb",
   "src/libANGLE/Context_gles_ext_autogen.h":
     "77046ddf577d922a38845e8b4de6aac0",
   "src/libANGLE/capture/capture_egl_autogen.cpp":
@@ -84,7 +84,7 @@
   "src/libANGLE/capture/capture_gles_ext_autogen.h":
     "acd990d31580a461eedcda4f60f7788b",
   "src/libANGLE/context_local_call_autogen.h":
-    "d83fa7906c0285f34c58eb69d4035ceb",
+    "6c6b737c8a10b6a5b8c6171df80b9487",
   "src/libANGLE/validationCL_autogen.h":
     "0022d0cdb6a9e2ef4a59b71164f62333",
   "src/libANGLE/validationEGL_autogen.h":
@@ -156,7 +156,7 @@
   "src/libGLESv2/entry_points_gles_1_0_autogen.h":
     "1d3aef77845a416497070985a8e9cb31",
   "src/libGLESv2/entry_points_gles_2_0_autogen.cpp":
-    "10275e24b36a86a2de5aba52b952ae8d",
+    "b98b2cbad9639e76dd6ba45cfaf95e1e",
   "src/libGLESv2/entry_points_gles_2_0_autogen.h":
     "691c60c2dfed9beca68aa1f32aa2c71b",
   "src/libGLESv2/entry_points_gles_3_0_autogen.cpp":
@@ -168,11 +168,11 @@
   "src/libGLESv2/entry_points_gles_3_1_autogen.h":
     "a7327c330a91665fc31accbb78793b42",
   "src/libGLESv2/entry_points_gles_3_2_autogen.cpp":
-    "c3c6e66328d6eca21c273aaa7cb5fc97",
+    "114a390b7b97a4098fefd85d20a48a39",
   "src/libGLESv2/entry_points_gles_3_2_autogen.h":
     "647f932a299cdb4726b60bbba059f0d2",
   "src/libGLESv2/entry_points_gles_ext_autogen.cpp":
-    "0655076ef6d7a5b16b524a0d1a9ebe64",
+    "b0f655670a8c3b4801b2bd520b0f1f15",
   "src/libGLESv2/entry_points_gles_ext_autogen.h":
     "7bb44566362d1de21552faf427517085",
   "src/libGLESv2/libGLESv2_autogen.cpp":
diff --git a/scripts/generate_entry_points.py b/scripts/generate_entry_points.py
index 099dd20..cf58256 100755
--- a/scripts/generate_entry_points.py
+++ b/scripts/generate_entry_points.py
@@ -142,6 +142,10 @@
     'glColorMask',
     'glColorMaski',
     'glDepthMask',
+    'glDisable',
+    'glDisablei',
+    'glEnable',
+    'glEnablei',
     # GLES1 entry points
     'glClearColorx',
     'glClearDepthx',
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index c29035d..2f5416c 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -6048,36 +6048,12 @@
     mState.setClipControl(originPacked, depthPacked);
 }
 
-void Context::disable(GLenum cap)
-{
-    mState.setEnableFeature(cap, false);
-    mStateCache.onContextCapChange(this);
-}
-
-void Context::disablei(GLenum target, GLuint index)
-{
-    mState.setEnableFeatureIndexed(target, false, index);
-    mStateCache.onContextCapChange(this);
-}
-
 void Context::disableVertexAttribArray(GLuint index)
 {
     mState.setEnableVertexAttribArray(index, false);
     mStateCache.onVertexArrayStateChange(this);
 }
 
-void Context::enable(GLenum cap)
-{
-    mState.setEnableFeature(cap, true);
-    mStateCache.onContextCapChange(this);
-}
-
-void Context::enablei(GLenum target, GLuint index)
-{
-    mState.setEnableFeatureIndexed(target, true, index);
-    mStateCache.onContextCapChange(this);
-}
-
 void Context::enableVertexAttribArray(GLuint index)
 {
     mState.setEnableVertexAttribArray(index, true);
@@ -10145,6 +10121,13 @@
                                                          format, type, pixels));
 }
 
+void Context::setLogicOpEnabledForGLES1(bool enabled)
+{
+    // Same implementation as ContextLocalEnable(GL_COLOR_LOGIC_OP), without the GLES1 forwarding.
+    getMutableLocalState()->setLogicOpEnabled(enabled);
+    onContextLocalCapChange();
+}
+
 void Context::logicOpANGLE(LogicalOperation opcodePacked)
 {
     mState.setLogicOp(opcodePacked);
@@ -10673,9 +10656,9 @@
     updateBasicDrawStatesError();
 }
 
-void StateCache::onContextCapChange(Context *context)
+void StateCache::onContextLocalCapChange(Context *context)
 {
-    updateBasicDrawStatesError();
+    mIsCachedBasicDrawStatesErrorValid = false;
 }
 
 void StateCache::onStencilStateChange(Context *context)
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index 9c6e47e..c655403 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -155,7 +155,7 @@
     // 4. onVertexArrayStateChange.
     // 5. onVertexArrayBufferStateChange.
     // 6. onDrawFramebufferChange.
-    // 7. onContextCapChange.
+    // 7. onContextLocalCapChange.
     // 8. onStencilStateChange.
     // 9. onDefaultVertexAttributeChange.
     // 10. onActiveTextureChange.
@@ -275,7 +275,6 @@
     void onVertexArrayBufferStateChange(Context *context);
     void onGLES1ClientStateChange(Context *context);
     void onDrawFramebufferChange(Context *context);
-    void onContextCapChange(Context *context);
     void onStencilStateChange(Context *context);
     void onDefaultVertexAttributeChange(Context *context);
     void onActiveTextureChange(Context *context);
@@ -284,10 +283,15 @@
     void onUniformBufferStateChange(Context *context);
     void onAtomicCounterBufferStateChange(Context *context);
     void onShaderStorageBufferStateChange(Context *context);
-    void onContextLocalColorMaskChange(Context *context);
     void onBufferBindingChange(Context *context);
     void onBlendFuncIndexedChange(Context *context);
     void onBlendEquationChange(Context *context);
+    // The following state change notifications are only called from context-local state change
+    // functions.  They only affect the draw validation cache which is also context-local (i.e. not
+    // accessed by other contexts in the share group).  Note that context-local state change
+    // functions are called without holding the share group lock.
+    void onContextLocalCapChange(Context *context);
+    void onContextLocalColorMaskChange(Context *context);
 
   private:
     // Cache update functions.
@@ -569,6 +573,7 @@
 
     // To be used **only** directly by the entry points.
     LocalState *getMutableLocalState() { return mState.getMutableLocalState(); }
+    void onContextLocalCapChange() { mStateCache.onContextLocalCapChange(this); }
     void onContextLocalColorMaskChange() { mStateCache.onContextLocalColorMaskChange(this); }
 
     bool skipValidation() const
@@ -703,7 +708,12 @@
     bool isDestroyed() const { return mIsDestroyed; }
     void setIsDestroyed() { mIsDestroyed = true; }
 
-    void setLogicOpEnabled(bool enabled) { mState.setLogicOpEnabled(enabled); }
+    // This function acts as glEnable(GL_COLOR_LOGIC_OP), but it's called from the GLES1 emulation
+    // code to implement logicOp using the non-GLES1 functionality (i.e. GL_ANGLE_logic_op).  The
+    // ContextLocalEnable() entry point implementation cannot be used (as ContextLocal* functions
+    // are typically used by other frontend-emulated features) because it forwards this back to
+    // GLES1.
+    void setLogicOpEnabledForGLES1(bool enabled);
     void setLogicOp(LogicalOperation opcode) { mState.setLogicOp(opcode); }
 
     // Needed by capture serialization logic that works with a "const" Context pointer.
diff --git a/src/libANGLE/Context_gles_2_0_autogen.h b/src/libANGLE/Context_gles_2_0_autogen.h
index 5590cae..88d509f 100644
--- a/src/libANGLE/Context_gles_2_0_autogen.h
+++ b/src/libANGLE/Context_gles_2_0_autogen.h
@@ -53,12 +53,10 @@
     void depthFunc(GLenum func);                                                                   \
     void depthRangef(GLfloat n, GLfloat f);                                                        \
     void detachShader(ShaderProgramID programPacked, ShaderProgramID shaderPacked);                \
-    void disable(GLenum cap);                                                                      \
     void disableVertexAttribArray(GLuint index);                                                   \
     void drawArrays(PrimitiveMode modePacked, GLint first, GLsizei count);                         \
     void drawElements(PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked,        \
                       const void *indices);                                                        \
-    void enable(GLenum cap);                                                                       \
     void enableVertexAttribArray(GLuint index);                                                    \
     void finish();                                                                                 \
     void flush();                                                                                  \
diff --git a/src/libANGLE/Context_gles_3_2_autogen.h b/src/libANGLE/Context_gles_3_2_autogen.h
index 186646d..150c095 100644
--- a/src/libANGLE/Context_gles_3_2_autogen.h
+++ b/src/libANGLE/Context_gles_3_2_autogen.h
@@ -26,7 +26,6 @@
                              const GLuint *ids, GLboolean enabled);                                \
     void debugMessageInsert(GLenum source, GLenum type, GLuint id, GLenum severity,                \
                             GLsizei length, const GLchar *buf);                                    \
-    void disablei(GLenum target, GLuint index);                                                    \
     void drawElementsBaseVertex(PrimitiveMode modePacked, GLsizei count,                           \
                                 DrawElementsType typePacked, const void *indices,                  \
                                 GLint basevertex);                                                 \
@@ -36,7 +35,6 @@
     void drawRangeElementsBaseVertex(PrimitiveMode modePacked, GLuint start, GLuint end,           \
                                      GLsizei count, DrawElementsType typePacked,                   \
                                      const void *indices, GLint basevertex);                       \
-    void enablei(GLenum target, GLuint index);                                                     \
     void framebufferTexture(GLenum target, GLenum attachment, TextureID texturePacked,             \
                             GLint level);                                                          \
     GLuint getDebugMessageLog(GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types,       \
diff --git a/src/libANGLE/GLES1Renderer.cpp b/src/libANGLE/GLES1Renderer.cpp
index 3f193dd..73f0ff7 100644
--- a/src/libANGLE/GLES1Renderer.cpp
+++ b/src/libANGLE/GLES1Renderer.cpp
@@ -286,7 +286,9 @@
 
     if (gles1State.isDirty(GLES1State::DIRTY_GLES1_LOGIC_OP) && hasLogicOpANGLE)
     {
-        context->setLogicOpEnabled(gles1State.mLogicOpEnabled);
+        // Note: ContextLocalEnable(GL_COLOR_LOGIC_OP) is not used because that entry point
+        // implementation forwards logicOp back to GLES1State.
+        context->setLogicOpEnabledForGLES1(gles1State.mLogicOpEnabled);
         context->setLogicOp(gles1State.mLogicOp);
     }
     else if (hasFramebufferFetch)
diff --git a/src/libANGLE/PixelLocalStorage.cpp b/src/libANGLE/PixelLocalStorage.cpp
index 0843651..03e1014 100644
--- a/src/libANGLE/PixelLocalStorage.cpp
+++ b/src/libANGLE/PixelLocalStorage.cpp
@@ -66,7 +66,7 @@
     {
         if (mScissorTestEnabled)
         {
-            mContext->disable(GL_SCISSOR_TEST);
+            ContextLocalDisable(mContext, GL_SCISSOR_TEST);
         }
     }
 
@@ -74,7 +74,7 @@
     {
         if (mScissorTestEnabled)
         {
-            mContext->enable(GL_SCISSOR_TEST);
+            ContextLocalEnable(mContext, GL_SCISSOR_TEST);
         }
     }
 
@@ -852,7 +852,7 @@
             ASSERT(caps.maxColorAttachmentsWithActivePixelLocalStorage == 0);
             if (state.isBlendEnabled())
             {
-                context->disable(GL_BLEND);
+                ContextLocalDisable(context, GL_BLEND);
                 mBlendsToReEnable.set(0);
             }
             std::array<bool, 4> &mask = mSavedColorMasks[0];
@@ -883,7 +883,7 @@
                 // Ensure blend and color mask are disabled for this draw buffer.
                 if (state.isBlendEnabledIndexed(drawBufferIdx))
                 {
-                    context->disablei(GL_BLEND, drawBufferIdx);
+                    ContextLocalDisablei(context, GL_BLEND, drawBufferIdx);
                     mBlendsToReEnable.set(drawBufferIdx);
                 }
                 std::array<bool, 4> &mask = mSavedColorMasks[drawBufferIdx];
@@ -961,7 +961,7 @@
             // change while pixel local storage was active.
             if (mBlendsToReEnable[0])
             {
-                context->enable(GL_BLEND);
+                ContextLocalEnable(context, GL_BLEND);
             }
             if (mColorMasksToRestore[0])
             {
@@ -986,7 +986,7 @@
                 // these did not change while pixel local storage was active.
                 if (mBlendsToReEnable[drawBufferIdx])
                 {
-                    context->enablei(GL_BLEND, drawBufferIdx);
+                    ContextLocalEnablei(context, GL_BLEND, drawBufferIdx);
                 }
                 if (mColorMasksToRestore[drawBufferIdx])
                 {
diff --git a/src/libANGLE/State.h b/src/libANGLE/State.h
index bd26953..dbe5aaf 100644
--- a/src/libANGLE/State.h
+++ b/src/libANGLE/State.h
@@ -1247,18 +1247,13 @@
     float getDepthClearValue() const { return mLocalState.getDepthClearValue(); }
     int getStencilClearValue() const { return mLocalState.getStencilClearValue(); }
     bool isRasterizerDiscardEnabled() const { return mLocalState.isRasterizerDiscardEnabled(); }
-    void setRasterizerDiscard(bool enabled) { mLocalState.setRasterizerDiscard(enabled); }
     bool isPrimitiveRestartEnabled() const { return mLocalState.isPrimitiveRestartEnabled(); }
-    void setPrimitiveRestart(bool enabled) { mLocalState.setPrimitiveRestart(enabled); }
     bool isCullFaceEnabled() const { return mLocalState.isCullFaceEnabled(); }
-    void setCullFace(bool enabled) { mLocalState.setCullFace(enabled); }
     void setCullMode(CullFaceMode mode) { mLocalState.setCullMode(mode); }
     void setFrontFace(GLenum front) { mLocalState.setFrontFace(front); }
     bool isDepthClampEnabled() const { return mLocalState.isDepthClampEnabled(); }
-    void setDepthClamp(bool enabled) { mLocalState.setDepthClamp(enabled); }
     bool isDepthTestEnabled() const { return mLocalState.isDepthTestEnabled(); }
     bool isDepthWriteEnabled() const { return mLocalState.isDepthWriteEnabled(); }
-    void setDepthTest(bool enabled) { mLocalState.setDepthTest(enabled); }
     void setDepthFunc(GLenum depthFunc) { mLocalState.setDepthFunc(depthFunc); }
     void setDepthRange(float zNear, float zFar) { mLocalState.setDepthRange(zNear, zFar); }
     float getNearPlane() const { return mLocalState.getNearPlane(); }
@@ -1279,11 +1274,6 @@
     {
         return mLocalState.getBlendEnabledDrawBufferMask();
     }
-    void setBlend(bool enabled) { mLocalState.setBlend(enabled); }
-    void setBlendIndexed(bool enabled, GLuint index)
-    {
-        mLocalState.setBlendIndexed(enabled, index);
-    }
     void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
     {
         mLocalState.setBlendFactors(sourceRGB, destRGB, sourceAlpha, destAlpha);
@@ -1311,7 +1301,6 @@
     const ColorF &getBlendColor() const { return mLocalState.getBlendColor(); }
     bool isStencilTestEnabled() const { return mLocalState.isStencilTestEnabled(); }
     bool isStencilWriteEnabled() const { return mLocalState.isStencilWriteEnabled(); }
-    void setStencilTest(bool enabled) { mLocalState.setStencilTest(enabled); }
     void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
     {
         mLocalState.setStencilParams(stencilFunc, stencilRef, stencilMask);
@@ -1349,9 +1338,6 @@
     bool isPolygonOffsetLineEnabled() const { return mLocalState.isPolygonOffsetLineEnabled(); }
     bool isPolygonOffsetFillEnabled() const { return mLocalState.isPolygonOffsetFillEnabled(); }
     bool isPolygonOffsetEnabled() const { return mLocalState.isPolygonOffsetEnabled(); }
-    void setPolygonOffsetPoint(bool enabled) { mLocalState.setPolygonOffsetPoint(enabled); }
-    void setPolygonOffsetLine(bool enabled) { mLocalState.setPolygonOffsetLine(enabled); }
-    void setPolygonOffsetFill(bool enabled) { mLocalState.setPolygonOffsetFill(enabled); }
     void setPolygonOffsetParams(GLfloat factor, GLfloat units, GLfloat clamp)
     {
         mLocalState.setPolygonOffsetParams(factor, units, clamp);
@@ -1360,9 +1346,7 @@
     {
         return mLocalState.isSampleAlphaToCoverageEnabled();
     }
-    void setSampleAlphaToCoverage(bool enabled) { mLocalState.setSampleAlphaToCoverage(enabled); }
     bool isSampleCoverageEnabled() const { return mLocalState.isSampleCoverageEnabled(); }
-    void setSampleCoverage(bool enabled) { mLocalState.setSampleCoverage(enabled); }
     void setSampleCoverageParams(GLclampf value, bool invert)
     {
         mLocalState.setSampleCoverageParams(value, invert);
@@ -1370,7 +1354,6 @@
     GLclampf getSampleCoverageValue() const { return mLocalState.getSampleCoverageValue(); }
     bool getSampleCoverageInvert() const { return mLocalState.getSampleCoverageInvert(); }
     bool isSampleMaskEnabled() const { return mLocalState.isSampleMaskEnabled(); }
-    void setSampleMaskEnabled(bool enabled) { mLocalState.setSampleMaskEnabled(enabled); }
     void setSampleMaskParams(GLuint maskNumber, GLbitfield mask)
     {
         mLocalState.setSampleMaskParams(maskNumber, mask);
@@ -1384,23 +1367,18 @@
         return mLocalState.getSampleMaskValues();
     }
     GLuint getMaxSampleMaskWords() const { return mLocalState.getMaxSampleMaskWords(); }
-    void setSampleAlphaToOne(bool enabled) { mLocalState.setSampleAlphaToOne(enabled); }
     bool isSampleAlphaToOneEnabled() const { return mLocalState.isSampleAlphaToOneEnabled(); }
-    void setMultisampling(bool enabled) { mLocalState.setMultisampling(enabled); }
     bool isMultisamplingEnabled() const { return mLocalState.isMultisamplingEnabled(); }
-    void setSampleShading(bool enabled) { mLocalState.setSampleShading(enabled); }
     bool isSampleShadingEnabled() const { return mLocalState.isSampleShadingEnabled(); }
     void setMinSampleShading(float value) { mLocalState.setMinSampleShading(value); }
     float getMinSampleShading() const { return mLocalState.getMinSampleShading(); }
     bool isScissorTestEnabled() const { return mLocalState.isScissorTestEnabled(); }
-    void setScissorTest(bool enabled) { mLocalState.setScissorTest(enabled); }
     void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
     {
         mLocalState.setScissorParams(x, y, width, height);
     }
     const Rectangle &getScissor() const { return mLocalState.getScissor(); }
     bool isDitherEnabled() const { return mLocalState.isDitherEnabled(); }
-    void setDither(bool enabled) { mLocalState.setDither(enabled); }
     bool isBindGeneratesResourceEnabled() const
     {
         return mLocalState.isBindGeneratesResourceEnabled();
@@ -1446,7 +1424,6 @@
     PixelUnpackState &getUnpackState() { return mLocalState.getUnpackState(); }
     void setCoverageModulation(GLenum components) { mLocalState.setCoverageModulation(components); }
     GLenum getCoverageModulation() const { return mLocalState.getCoverageModulation(); }
-    void setFramebufferSRGB(bool sRGB) { mLocalState.setFramebufferSRGB(sRGB); }
     bool getFramebufferSRGB() const { return mLocalState.getFramebufferSRGB(); }
     void setMaxShaderCompilerThreads(GLuint count)
     {
@@ -1504,10 +1481,6 @@
     {
         return mLocalState.getEnabledClipDistances();
     }
-    void setClipDistanceEnable(int idx, bool enable)
-    {
-        mLocalState.setClipDistanceEnable(idx, enable);
-    }
     bool noSimultaneousConstantColorAndAlphaBlendFunc() const
     {
         return mLocalState.noSimultaneousConstantColorAndAlphaBlendFunc();
@@ -1540,7 +1513,6 @@
     {
         return mLocalState.getBlendFuncConstantColorDrawBuffers();
     }
-    void setLogicOpEnabled(bool enabled) { mLocalState.setLogicOpEnabled(enabled); }
     bool isLogicOpEnabled() const { return mLocalState.isLogicOpEnabled(); }
     void setLogicOp(LogicalOperation opcode) { mLocalState.setLogicOp(opcode); }
     LogicalOperation getLogicOp() const { return mLocalState.getLogicOp(); }
@@ -1558,14 +1530,6 @@
     }
     const Debug &getDebug() const { return mLocalState.getDebug(); }
     Debug &getDebug() { return mLocalState.getDebug(); }
-    void setEnableFeature(GLenum feature, bool enabled)
-    {
-        mLocalState.setEnableFeature(feature, enabled);
-    }
-    void setEnableFeatureIndexed(GLenum feature, bool enabled, GLuint index)
-    {
-        mLocalState.setEnableFeatureIndexed(feature, enabled, index);
-    }
     bool getEnableFeature(GLenum feature) const { return mLocalState.getEnableFeature(feature); }
     bool getEnableFeatureIndexed(GLenum feature, GLuint index) const
     {
diff --git a/src/libANGLE/context_local_call.cpp b/src/libANGLE/context_local_call.cpp
index 50b0eac..876e96e 100644
--- a/src/libANGLE/context_local_call.cpp
+++ b/src/libANGLE/context_local_call.cpp
@@ -75,4 +75,28 @@
 {
     context->getMutableLocalState()->setDepthMask(ConvertToBool(flag));
 }
+
+void ContextLocalDisable(Context *context, GLenum cap)
+{
+    context->getMutableLocalState()->setEnableFeature(cap, false);
+    context->onContextLocalCapChange();
+}
+
+void ContextLocalDisablei(Context *context, GLenum target, GLuint index)
+{
+    context->getMutableLocalState()->setEnableFeatureIndexed(target, false, index);
+    context->onContextLocalCapChange();
+}
+
+void ContextLocalEnable(Context *context, GLenum cap)
+{
+    context->getMutableLocalState()->setEnableFeature(cap, true);
+    context->onContextLocalCapChange();
+}
+
+void ContextLocalEnablei(Context *context, GLenum target, GLuint index)
+{
+    context->getMutableLocalState()->setEnableFeatureIndexed(target, true, index);
+    context->onContextLocalCapChange();
+}
 }  // namespace gl
diff --git a/src/libANGLE/context_local_call_autogen.h b/src/libANGLE/context_local_call_autogen.h
index e92c314..7022b7b 100644
--- a/src/libANGLE/context_local_call_autogen.h
+++ b/src/libANGLE/context_local_call_autogen.h
@@ -28,12 +28,16 @@
                            GLboolean blue,
                            GLboolean alpha);
 void ContextLocalDepthMask(Context *context, GLboolean flag);
+void ContextLocalDisable(Context *context, GLenum cap);
+void ContextLocalEnable(Context *context, GLenum cap);
 void ContextLocalColorMaski(Context *context,
                             GLuint index,
                             GLboolean r,
                             GLboolean g,
                             GLboolean b,
                             GLboolean a);
+void ContextLocalDisablei(Context *context, GLenum target, GLuint index);
+void ContextLocalEnablei(Context *context, GLenum target, GLuint index);
 void ContextLocalClearColorx(Context *context,
                              GLfixed red,
                              GLfixed green,
@@ -168,6 +172,8 @@
                             GLboolean g,
                             GLboolean b,
                             GLboolean a);
+void ContextLocalDisablei(Context *context, GLenum target, GLuint index);
+void ContextLocalEnablei(Context *context, GLenum target, GLuint index);
 
 // GL_EXT_draw_elements_base_vertex
 
@@ -340,6 +346,8 @@
                             GLboolean g,
                             GLboolean b,
                             GLboolean a);
+void ContextLocalDisablei(Context *context, GLenum target, GLuint index);
+void ContextLocalEnablei(Context *context, GLenum target, GLuint index);
 
 // GL_OES_draw_elements_base_vertex
 
diff --git a/src/libGLESv2/entry_points_gles_2_0_autogen.cpp b/src/libGLESv2/entry_points_gles_2_0_autogen.cpp
index 1ebccdc..28a4599 100644
--- a/src/libGLESv2/entry_points_gles_2_0_autogen.cpp
+++ b/src/libGLESv2/entry_points_gles_2_0_autogen.cpp
@@ -1124,12 +1124,11 @@
 
     if (context)
     {
-        SCOPED_SHARE_CONTEXT_LOCK(context);
         bool isCallValid = (context->skipValidation() ||
                             ValidateDisable(context, angle::EntryPoint::GLDisable, cap));
         if (isCallValid)
         {
-            context->disable(cap);
+            ContextLocalDisable(context, cap);
         }
         ANGLE_CAPTURE_GL(Disable, isCallValid, context, cap);
     }
@@ -1228,12 +1227,11 @@
 
     if (context)
     {
-        SCOPED_SHARE_CONTEXT_LOCK(context);
         bool isCallValid = (context->skipValidation() ||
                             ValidateEnable(context, angle::EntryPoint::GLEnable, cap));
         if (isCallValid)
         {
-            context->enable(cap);
+            ContextLocalEnable(context, cap);
         }
         ANGLE_CAPTURE_GL(Enable, isCallValid, context, cap);
     }
diff --git a/src/libGLESv2/entry_points_gles_3_2_autogen.cpp b/src/libGLESv2/entry_points_gles_3_2_autogen.cpp
index 2dcc2be..b34960d 100644
--- a/src/libGLESv2/entry_points_gles_3_2_autogen.cpp
+++ b/src/libGLESv2/entry_points_gles_3_2_autogen.cpp
@@ -343,13 +343,12 @@
 
     if (context)
     {
-        SCOPED_SHARE_CONTEXT_LOCK(context);
         bool isCallValid =
             (context->skipValidation() ||
              ValidateDisablei(context, angle::EntryPoint::GLDisablei, target, index));
         if (isCallValid)
         {
-            context->disablei(target, index);
+            ContextLocalDisablei(context, target, index);
         }
         ANGLE_CAPTURE_GL(Disablei, isCallValid, context, target, index);
     }
@@ -482,12 +481,11 @@
 
     if (context)
     {
-        SCOPED_SHARE_CONTEXT_LOCK(context);
         bool isCallValid = (context->skipValidation() ||
                             ValidateEnablei(context, angle::EntryPoint::GLEnablei, target, index));
         if (isCallValid)
         {
-            context->enablei(target, index);
+            ContextLocalEnablei(context, target, index);
         }
         ANGLE_CAPTURE_GL(Enablei, isCallValid, context, target, index);
     }
diff --git a/src/libGLESv2/entry_points_gles_ext_autogen.cpp b/src/libGLESv2/entry_points_gles_ext_autogen.cpp
index 90a1605..d1c8a4c 100644
--- a/src/libGLESv2/entry_points_gles_ext_autogen.cpp
+++ b/src/libGLESv2/entry_points_gles_ext_autogen.cpp
@@ -6027,13 +6027,12 @@
 
     if (context)
     {
-        SCOPED_SHARE_CONTEXT_LOCK(context);
         bool isCallValid =
             (context->skipValidation() ||
              ValidateDisableiEXT(context, angle::EntryPoint::GLDisableiEXT, target, index));
         if (isCallValid)
         {
-            context->disablei(target, index);
+            ContextLocalDisablei(context, target, index);
         }
         ANGLE_CAPTURE_GL(DisableiEXT, isCallValid, context, target, index);
     }
@@ -6052,13 +6051,12 @@
 
     if (context)
     {
-        SCOPED_SHARE_CONTEXT_LOCK(context);
         bool isCallValid =
             (context->skipValidation() ||
              ValidateEnableiEXT(context, angle::EntryPoint::GLEnableiEXT, target, index));
         if (isCallValid)
         {
-            context->enablei(target, index);
+            ContextLocalEnablei(context, target, index);
         }
         ANGLE_CAPTURE_GL(EnableiEXT, isCallValid, context, target, index);
     }
@@ -10690,13 +10688,12 @@
 
     if (context)
     {
-        SCOPED_SHARE_CONTEXT_LOCK(context);
         bool isCallValid =
             (context->skipValidation() ||
              ValidateDisableiOES(context, angle::EntryPoint::GLDisableiOES, target, index));
         if (isCallValid)
         {
-            context->disablei(target, index);
+            ContextLocalDisablei(context, target, index);
         }
         ANGLE_CAPTURE_GL(DisableiOES, isCallValid, context, target, index);
     }
@@ -10715,13 +10712,12 @@
 
     if (context)
     {
-        SCOPED_SHARE_CONTEXT_LOCK(context);
         bool isCallValid =
             (context->skipValidation() ||
              ValidateEnableiOES(context, angle::EntryPoint::GLEnableiOES, target, index));
         if (isCallValid)
         {
-            context->enablei(target, index);
+            ContextLocalEnablei(context, target, index);
         }
         ANGLE_CAPTURE_GL(EnableiOES, isCallValid, context, target, index);
     }