Cache all stencil related glGet's

This is used in testufo a lot (per frame).

Change-Id: I882e7b542c75702326474438eeb77aaeea0e1c4c
diff --git a/shared/OpenglCodecCommon/GLClientState.cpp b/shared/OpenglCodecCommon/GLClientState.cpp
index 017bf71..93f9d5d 100644
--- a/shared/OpenglCodecCommon/GLClientState.cpp
+++ b/shared/OpenglCodecCommon/GLClientState.cpp
@@ -39,6 +39,24 @@
 void GLClientState::init() {
     m_initialized = false;
 
+    state_GL_STENCIL_TEST = false;
+    state_GL_STENCIL_FUNC = GL_ALWAYS;
+    state_GL_STENCIL_VALUE_MASK = ~(0);
+    state_GL_STENCIL_REF = 0;
+    state_GL_STENCIL_FAIL = GL_KEEP;
+    state_GL_STENCIL_PASS_DEPTH_FAIL = GL_KEEP;
+    state_GL_STENCIL_PASS_DEPTH_PASS = GL_KEEP;
+    state_GL_STENCIL_BACK_FUNC = GL_ALWAYS;
+    state_GL_STENCIL_BACK_VALUE_MASK = ~(0);
+    state_GL_STENCIL_BACK_REF = 0;
+    state_GL_STENCIL_BACK_FAIL = GL_KEEP;
+    state_GL_STENCIL_BACK_PASS_DEPTH_FAIL = GL_KEEP;
+    state_GL_STENCIL_BACK_PASS_DEPTH_PASS = GL_KEEP;
+    state_GL_STENCIL_WRITEMASK = ~(0);
+    state_GL_STENCIL_BACK_WRITEMASK = ~(0);
+    state_GL_STENCIL_CLEAR_VALUE = 0;
+
+
     m_arrayBuffer = 0;
     m_arrayBuffer_lastEncode = 0;
 
@@ -2939,6 +2957,44 @@
     return m_transformFeedbackVaryingsCountForLinking;
 }
 
+void GLClientState::stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) {
+    if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
+        state_GL_STENCIL_FUNC = func;
+        state_GL_STENCIL_REF = ref;
+        state_GL_STENCIL_VALUE_MASK = mask;
+    }
+
+    if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
+        state_GL_STENCIL_BACK_FUNC = func;
+        state_GL_STENCIL_BACK_REF = ref;
+        state_GL_STENCIL_BACK_VALUE_MASK = mask;
+    }
+}
+
+void GLClientState::stencilMaskSeparate(GLenum face, GLuint mask) {
+    if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
+        state_GL_STENCIL_WRITEMASK = mask;
+    }
+
+    if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
+        state_GL_STENCIL_BACK_WRITEMASK = mask;
+    }
+}
+
+void GLClientState::stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
+    if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
+        state_GL_STENCIL_FAIL = fail;
+        state_GL_STENCIL_PASS_DEPTH_FAIL = zfail;
+        state_GL_STENCIL_PASS_DEPTH_PASS = zpass;
+    }
+
+    if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
+        state_GL_STENCIL_BACK_FAIL = fail;
+        state_GL_STENCIL_BACK_PASS_DEPTH_FAIL = zfail;
+        state_GL_STENCIL_BACK_PASS_DEPTH_PASS = zpass;
+    }
+}
+
 void GLClientState::setTextureData(SharedTextureDataMap* sharedTexData) {
     m_tex.textureRecs = sharedTexData;
 }
diff --git a/shared/OpenglCodecCommon/GLClientState.h b/shared/OpenglCodecCommon/GLClientState.h
index 147e3d4..c0ca53a 100644
--- a/shared/OpenglCodecCommon/GLClientState.h
+++ b/shared/OpenglCodecCommon/GLClientState.h
@@ -514,6 +514,11 @@
     bool getTransformFeedbackActiveUnpaused() const;
     uint32_t getTransformFeedbackVaryingsCountForLinking() const;
 
+    // Stencil state
+    void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
+    void stencilMaskSeparate(GLenum face, GLuint mask);
+    void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+
     void setTextureData(SharedTextureDataMap* sharedTexData);
     void setRenderbufferInfo(RenderbufferInfo* rbInfo);
     void setSamplerInfo(SamplerInfo* samplerInfo);
@@ -554,6 +559,23 @@
     // Attrib validation
     bool isAttribIndexUsedByProgram(int attribIndex);
 
+    // Fast access to some enables and stencil related glGet's
+    bool state_GL_STENCIL_TEST;
+    GLenum state_GL_STENCIL_FUNC;
+    unsigned int state_GL_STENCIL_VALUE_MASK;
+    int state_GL_STENCIL_REF;
+    GLenum state_GL_STENCIL_FAIL;
+    GLenum state_GL_STENCIL_PASS_DEPTH_FAIL;
+    GLenum state_GL_STENCIL_PASS_DEPTH_PASS;
+    GLenum state_GL_STENCIL_BACK_FUNC;
+    unsigned int state_GL_STENCIL_BACK_VALUE_MASK;
+    int state_GL_STENCIL_BACK_REF;
+    GLenum state_GL_STENCIL_BACK_FAIL;
+    GLenum state_GL_STENCIL_BACK_PASS_DEPTH_FAIL;
+    GLenum state_GL_STENCIL_BACK_PASS_DEPTH_PASS;
+    unsigned int state_GL_STENCIL_WRITEMASK;
+    unsigned int state_GL_STENCIL_BACK_WRITEMASK;
+    int state_GL_STENCIL_CLEAR_VALUE;
 private:
     void init();
     bool m_initialized;
@@ -967,6 +989,79 @@
             isClientStateParam = true;
             break;
         }
+        case GL_FRAMEBUFFER_BINDING:
+        // also case GL_DRAW_FRAMEBUFFER_BINDING:
+            *out = (T)mFboState.boundDrawFramebuffer;
+            isClientStateParam = true;
+            break;
+        case 0x8CAA: // GL_READ_FRAMEBUFFER_BINDING
+            *out = (T)mFboState.boundReadFramebuffer;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_TEST:
+            *out = (T)state_GL_STENCIL_TEST;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_FUNC:
+            *out = (T)state_GL_STENCIL_FUNC;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_VALUE_MASK:
+            *out = (T)state_GL_STENCIL_VALUE_MASK;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_REF:
+            *out = (T)state_GL_STENCIL_REF;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_FAIL:
+            *out = (T)state_GL_STENCIL_FAIL;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_PASS_DEPTH_FAIL:
+            *out = (T)state_GL_STENCIL_PASS_DEPTH_FAIL;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_PASS_DEPTH_PASS:
+            *out = (T)state_GL_STENCIL_PASS_DEPTH_PASS;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_BACK_FUNC:
+            *out = (T)state_GL_STENCIL_BACK_FUNC;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_BACK_VALUE_MASK:
+            *out = (T)state_GL_STENCIL_BACK_VALUE_MASK;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_BACK_REF:
+            *out = (T)state_GL_STENCIL_BACK_REF;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_BACK_FAIL:
+            *out = (T)state_GL_STENCIL_BACK_FAIL;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+            *out = (T)state_GL_STENCIL_BACK_PASS_DEPTH_FAIL;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+            *out = (T)state_GL_STENCIL_BACK_PASS_DEPTH_PASS;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_WRITEMASK:
+            *out = (T)state_GL_STENCIL_WRITEMASK;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_BACK_WRITEMASK:
+            *out = (T)state_GL_STENCIL_BACK_WRITEMASK;
+            isClientStateParam = true;
+            break;
+        case GL_STENCIL_CLEAR_VALUE:
+            *out = (T)state_GL_STENCIL_CLEAR_VALUE;
+            isClientStateParam = true;
+            break;
         }
         return isClientStateParam;
     }
diff --git a/system/GLESv2_enc/GL2Encoder.cpp b/system/GLESv2_enc/GL2Encoder.cpp
index ba6944c..6f328d6 100755
--- a/system/GLESv2_enc/GL2Encoder.cpp
+++ b/system/GLESv2_enc/GL2Encoder.cpp
@@ -454,6 +454,9 @@
     OVERRIDE(glHint);
 
     OVERRIDE(glGetFragDataLocation);
+
+    OVERRIDE(glStencilMask);
+    OVERRIDE(glClearStencil);
 }
 
 GL2Encoder::~GL2Encoder()
@@ -811,16 +814,15 @@
         }
         break;
     case GL_TEXTURE_BINDING_2D:
-        SET_ERROR_IF(!state, GL_INVALID_OPERATION);
+        if (!state) return;
         *ptr = state->getBoundTexture(GL_TEXTURE_2D);
         break;
     case GL_TEXTURE_BINDING_EXTERNAL_OES:
-        SET_ERROR_IF(!state, GL_INVALID_OPERATION);
+        if (!state) return;
         *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES);
         break;
 
     case GL_MAX_VERTEX_ATTRIBS:
-        SET_ERROR_IF(!state, GL_INVALID_OPERATION);
         *ptr = CODEC_MAX_VERTEX_ATTRIBUTES;
         break;
     case GL_MAX_VERTEX_ATTRIB_STRIDE:
@@ -973,7 +975,7 @@
         *ptr = GL_LOSE_CONTEXT_ON_RESET_EXT;
         break;
     default:
-        SET_ERROR_IF(!state, GL_INVALID_OPERATION);
+        if (!state) return;
         if (!state->getClientStateParameter<GLint>(param, ptr)) {
             ctx->safe_glGetIntegerv(param, ptr);
         }
@@ -1037,7 +1039,7 @@
     }
 
     default:
-        SET_ERROR_IF(!state, GL_INVALID_OPERATION);
+        if (!state) return;
         if (!state->getClientStateParameter<GLfloat>(param, ptr)) {
             ctx->safe_glGetFloatv(param, ptr);
         }
@@ -1101,7 +1103,7 @@
     }
 
     default:
-        SET_ERROR_IF(!state, GL_INVALID_OPERATION);
+        if (!state) return;
         if (!state->getClientStateParameter<GLboolean>(param, ptr)) {
             ctx->safe_glGetBooleanv(param, ptr);
         }
@@ -4866,11 +4868,15 @@
     GL2Encoder *ctx = (GL2Encoder *)self;
 
 	SET_ERROR_IF(!GLESv2Validation::allowedEnable(ctx->majorVersion(), ctx->minorVersion(), what), GL_INVALID_ENUM);
+    if (!ctx->m_state) return;
 
     switch (what) {
     case GL_PRIMITIVE_RESTART_FIXED_INDEX:
         ctx->m_primitiveRestartEnabled = true;
         break;
+    case GL_STENCIL_TEST:
+        ctx->m_state->state_GL_STENCIL_TEST = true;
+        break;
     }
 
     ctx->m_glEnable_enc(ctx, what);
@@ -4880,11 +4886,15 @@
     GL2Encoder *ctx = (GL2Encoder *)self;
 
 	SET_ERROR_IF(!GLESv2Validation::allowedEnable(ctx->majorVersion(), ctx->minorVersion(), what), GL_INVALID_ENUM);
+    if (!ctx->m_state) return;
 
     switch (what) {
     case GL_PRIMITIVE_RESTART_FIXED_INDEX:
         ctx->m_primitiveRestartEnabled = false;
         break;
+    case GL_STENCIL_TEST:
+        ctx->m_state->state_GL_STENCIL_TEST = false;
+        break;
     }
 
     ctx->m_glDisable_enc(ctx, what);
@@ -6307,12 +6317,16 @@
 void GL2Encoder::s_glStencilFunc(void *self , GLenum func, GLint ref, GLuint mask) {
     GL2Encoder* ctx = (GL2Encoder*)self;
     SET_ERROR_IF(!GLESv2Validation::allowedFunc(func), GL_INVALID_ENUM);
+    if (!ctx->m_state) return;
+    ctx->m_state->stencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
     ctx->m_glStencilFunc_enc(ctx, func, ref, mask);
 }
 
 void GL2Encoder::s_glStencilFuncSeparate(void *self , GLenum face, GLenum func, GLint ref, GLuint mask) {
     GL2Encoder* ctx = (GL2Encoder*)self;
     SET_ERROR_IF(!GLESv2Validation::allowedFace(face) || !GLESv2Validation::allowedFunc(func), GL_INVALID_ENUM);
+    if (!ctx->m_state) return;
+    ctx->m_state->stencilFuncSeparate(face, func, ref, mask);
     ctx->m_glStencilFuncSeparate_enc(ctx, face, func, ref, mask);
 }
 
@@ -6323,6 +6337,8 @@
         !GLESv2Validation::allowedStencilOp(zfail) ||
         !GLESv2Validation::allowedStencilOp(zpass),
         GL_INVALID_ENUM);
+    if (!ctx->m_state) return;
+    ctx->m_state->stencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
     ctx->m_glStencilOp_enc(ctx, fail, zfail, zpass);
 }
 
@@ -6334,6 +6350,8 @@
         !GLESv2Validation::allowedStencilOp(zfail) ||
         !GLESv2Validation::allowedStencilOp(zpass),
         GL_INVALID_ENUM);
+    if (!ctx->m_state) return;
+    ctx->m_state->stencilOpSeparate(face, fail, zfail, zpass);
     ctx->m_glStencilOpSeparate_enc(ctx, face, fail, zfail, zpass);
 }
 
@@ -6342,6 +6360,8 @@
     SET_ERROR_IF(
         !GLESv2Validation::allowedFace(face),
         GL_INVALID_ENUM);
+    if (!ctx->m_state) return;
+    ctx->m_state->stencilMaskSeparate(face, mask);
     ctx->m_glStencilMaskSeparate_enc(ctx, face, mask);
 }
 
@@ -6570,3 +6590,17 @@
     RET_AND_SET_ERROR_IF(!ctx->m_shared->getProgramLinkStatus(program), GL_INVALID_OPERATION, -1);
     return ctx->m_glGetFragDataLocation_enc(ctx, program, name);
 }
+
+void GL2Encoder::s_glStencilMask(void* self, GLuint mask) {
+    GL2Encoder* ctx = (GL2Encoder*)self;
+    if (!ctx->m_state) return;
+    ctx->m_state->stencilMaskSeparate(GL_FRONT_AND_BACK, mask);
+    ctx->m_glStencilMask_enc(ctx, mask);
+}
+
+void GL2Encoder::s_glClearStencil(void* self, int v) {
+    GL2Encoder* ctx = (GL2Encoder*)self;
+    if (!ctx->m_state) return;
+    ctx->m_state->state_GL_STENCIL_CLEAR_VALUE = v;
+    ctx->m_glClearStencil_enc(ctx, v);
+}
diff --git a/system/GLESv2_enc/GL2Encoder.h b/system/GLESv2_enc/GL2Encoder.h
index 6be2687..93108eb 100644
--- a/system/GLESv2_enc/GL2Encoder.h
+++ b/system/GLESv2_enc/GL2Encoder.h
@@ -890,6 +890,9 @@
     static void s_glHint(void *self , GLenum target, GLenum mode);
     static GLint s_glGetFragDataLocation (void *self , GLuint program, const char* name);
 
+    static void s_glStencilMask(void* self, GLuint mask);
+    static void s_glClearStencil(void* self, int v);
+
 #define LIST_REMAINING_FUNCTIONS_FOR_VALIDATION(f) \
     f(glBindAttribLocation) \
     f(glUniformBlockBinding) \
@@ -933,6 +936,8 @@
     f(glIsEnabled) \
     f(glHint) \
     f(glGetFragDataLocation) \
+    f(glStencilMask) \
+    f(glClearStencil) \
 
 #define DECLARE_CLIENT_ENCODER_PROC(n) \
     n##_client_proc_t m_##n##_enc;