Commits

Murat Sari committed 64d4e32

[GLES]: Add init version of the state cache manager (thx master falcon). Make it a compile time option in cmake - its disabled by default.

Comments (0)

Files changed (17)

CMake/ConfigureBuild.cmake

 set(OGRE_SET_DISABLE_GLES2_CG_SUPPORT 0)
 set(OGRE_SET_DISABLE_GLES2_GLSL_OPTIMISER 0)
 set(OGRE_SET_DISABLE_GLES2_VAO_SUPPORT 0)
+set(OGRE_SET_DISABLE_GLES_STATE_CACHE_SUPPORT 0)
 set(RTSHADER_SYSTEM_BUILD_CORE_SHADERS 0)
 set(RTSHADER_SYSTEM_BUILD_EXT_SHADERS 0)
 set(OGRE_STATIC_LIB 0)
 if (NOT OGRE_CONFIG_ENABLE_GLES2_VAO_SUPPORT)
   set(OGRE_SET_DISABLE_GLES2_VAO_SUPPORT 1)
 endif()
+if (NOT OGRE_CONFIG_ENABLE_GLES_STATE_CACHE_SUPPORT)
+  set(OGRE_SET_DISABLE_GLES_STATE_CACHE_SUPPORT 1)
+endif()
 if (OGRE_STATIC)
   set(OGRE_STATIC_LIB 1)
 endif()

CMake/FeatureSummary.cmake

 if (OGRE_CONFIG_ENABLE_GLES2_VAO_SUPPORT)
 	set(_core "${_core}  + VertexArrayObjects for OpenGL ES 2.0\n")
 endif ()
-
+if (OGRE_CONFIG_ENABLE_GLES_STATE_CACHE_SUPPORT)
+	set(_core "${_core}  + StateCacheManager for OpenGL ES 1.x\n")
+endif ()
 if (DEFINED _core)
 	set(_features "${_features}Building core features:\n${_core}")
 endif ()

CMake/Templates/OgreBuildSettings.h.in

 
 #define OGRE_NO_GLES2_VAO_SUPPORT @OGRE_SET_DISABLE_GLES2_VAO_SUPPORT@
 
+#define OGRE_NO_GLES_STATE_CACHE_SUPPORT @OGRE_SET_DISABLE_GLES_STATE_CACHE_SUPPORT@
+
 #define OGRE_USE_BOOST @OGRE_SET_USE_BOOST@
 
 #define OGRE_PROFILING @OGRE_SET_PROFILING@
 cmake_dependent_option(OGRE_CONFIG_ENABLE_GLES2_CG_SUPPORT "Enable Cg support to ES 2 render system" FALSE "OGRE_BUILD_RENDERSYSTEM_GLES2" FALSE)
 cmake_dependent_option(OGRE_CONFIG_ENABLE_GLES2_GLSL_OPTIMISER "Enable GLSL optimiser use in GLES 2 render system" FALSE "OGRE_BUILD_RENDERSYSTEM_GLES2" FALSE)
 cmake_dependent_option(OGRE_CONFIG_ENABLE_GLES2_VAO_SUPPORT "Use VertexArrayObjects if possible." TRUE "OGRE_BUILD_RENDERSYSTEM_GLES2" FALSE)
+cmake_dependent_option(OGRE_CONFIG_ENABLE_GLES_STATE_CACHE_SUPPORT "Enable GLES state cache management" FALSE "OGRE_BUILD_RENDERSYSTEM_GLES" FALSE)
 cmake_dependent_option(OGRE_USE_BOOST "Use Boost extensions" TRUE "Boost_FOUND" FALSE)
 # Customise what to install 
 option(OGRE_INSTALL_SAMPLES "Install Ogre demos." FALSE)
   OGRE_CONFIG_ENABLE_GLES2_CG_SUPPORT
   OGRE_CONFIG_ENABLE_GLES2_GLSL_OPTIMISER
   OGRE_CONFIG_ENABLE_GLES2_VAO_SUPPORT
+  OGRE_CONFIG_ENABLE_GLES_STATE_CACHE_SUPPORT
   OGRE_USE_BOOST
   OGRE_INSTALL_SAMPLES_SOURCE
   OGRE_FULL_RPATH

RenderSystems/GLES/CMakeLists.txt

   include/OgreGLESTexture.h
   include/OgreGLESTextureManager.h
   include/OgreGLESManagedResource.h
+  include/OgreGLESStateCacheManager.h
 )
 
 
   src/OgreGLESSupport.cpp
   src/OgreGLESTexture.cpp
   src/OgreGLESTextureManager.cpp
+  src/OgreGLESStateCacheManager.cpp
 )
 
+include_directories(src/StateCacheManager)
+if(OGRE_CONFIG_ENABLE_GLES_STATE_CACHE_SUPPORT)
+  set(HEADER_FILES
+      ${HEADER_FILES} 
+      src/StateCacheManager/OgreGLESStateCacheManagerImp.h
+  )
+  set(SOURCE_FILES 
+      ${SOURCE_FILES}
+      src/StateCacheManager/OgreGLESStateCacheManagerImp.cpp
+  )
+else()
+  set(HEADER_FILES 
+      ${HEADER_FILES} 
+      src/StateCacheManager/OgreGLESNullStateCacheManagerImp.h
+  )
+  set(SOURCE_FILES 
+      ${SOURCE_FILES}
+      src/StateCacheManager/OgreGLESNullStateCacheManagerImp.cpp
+  )
+endif()
+
 # Add system specific settings
 if (WIN32)
   set(PLATFORM_HEADERS 

RenderSystems/GLES/include/OgreGLESPrerequisites.h

 #   define GL_BGRA  0x80E1
 #endif
 
+// Used for polygon modes
+#ifndef GL_FILL
+#   define GL_FILL    0x1B02
+#endif
+
 #if (OGRE_PLATFORM == OGRE_PLATFORM_WIN32) && !defined(__MINGW32__) && !defined(OGRE_STATIC_LIB)
 #   ifdef OGRE_GLESPLUGIN_EXPORTS
 #       define _OgreGLESExport __declspec(dllexport)

RenderSystems/GLES/include/OgreGLESRenderSystem.h

 #define __GLESRenderSystem_H__
 
 #include "OgreGLESPrerequisites.h"
-
 #include "OgreRenderSystem.h"
 
 namespace Ogre {
     class GLESRTTManager;
     class GLESGpuProgramManager;
     class HardwareBufferManager;
+    class GLESStateCacheManager;
 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
     class AndroidResourceManager;
 #endif
             /// Number of fixed-function texture units
             unsigned short mFixedFunctionTextureUnits;
 
-            /// Store last colour write state
-            bool mColourWrite[4];
-
-            /// Store last depth write state
-            GLboolean mDepthWrite;
-
-            /// Store last stencil mask state
-            uint32 mStencilMask;
-
             GLfloat mAutoTextureMatrix[16];
 
             bool mUseAutoTextureMatrix;
             size_t mTextureCount;
             bool mTextureEnabled;
-
+        
             /// GL support class, used for creating windows etc.
             GLESSupport *mGLSupport;
 
+            /// State cache manager which responsible to reduce redundant state changes
+            GLESStateCacheManager* mStateCacheManager;
+        
             /* The main GL context - main thread only */
             GLESContext *mMainContext;
 
               */
             GLESRTTManager *mRTTManager;
 
-            /** These variables are used for caching RenderSystem state.
-                They are cached because OpenGL state changes can be quite expensive,
-                which is especially important on mobile or embedded systems.
-             */
-            ushort mActiveTextureUnit;
-            ushort mActiveClientTextureUnit;
-            TexEnviMap mActiveTexEnviMap;
-            TexEnvfMap mActiveTexEnvfMap;
-            TexEnvfvMap mActiveTexEnvfvMap;
-            PointParamfMap mActivePointParamfMap;
-            PointParamfvMap mActivePointParamfvMap;
-            MaterialfvMap mActiveMaterialfvMap;
-            LightfMap mActiveLightfMap;
-            LightfvMap mActiveLightfvMap;
-            GLint mActiveSourceBlend;
-            GLint mActiveDestBlend;
-            GLint mActiveDepthFunc;
-            GLenum mActiveShadeModel;
-            GLenum mActiveMatrixMode;
-            GLfloat mActivePointSize;
-            GLenum mActiveCullFaceMode;
-            GLfloat mTexMaxAnisotropy;
-            GLfloat mMaxTexMaxAnisotropy;
-            GLclampf mActiveClearDepth;
-            ColourValue mActiveClearColor;
-            GLenum mActiveAlphaFunc;
-            GLclampf mActiveAlphaFuncValue;
-
             /// Check if the GL system has already been initialised
             bool mGLInitialised;
 
-            /// Mask of buffers who contents can be discarded if GL_EXT_discard_framebuffer is supported
-            unsigned int mDiscardBuffers;
-
-            /** OpenGL ES doesn't support setting the PolygonMode like desktop GL
-                So we will cache the value and set it manually
-             */
-            GLenum mPolygonMode;
-
             GLuint getCombinedMinMipFilter(void) const;
 
             GLint getTextureAddressingMode(TextureUnitState::TextureAddressingMode tam) const;
 
             bool activateGLTextureUnit(size_t unit);
             bool activateGLClientTextureUnit(size_t unit);
-            void setGLTexEnvi(GLenum target, GLenum name, GLint param);
-            void setGLTexEnvf(GLenum target, GLenum name, GLfloat param);
-            void setGLTexEnvfv(GLenum target, GLenum name, const GLfloat *param);
-            void setGLPointParamf(GLenum name, GLfloat param);
-            void setGLPointParamfv(GLenum name, const GLfloat *param);
-            void setGLMaterialfv(GLenum face, GLenum name, const GLfloat *param);
-            void setGLMatrixMode(GLenum mode);
-            void setGLDepthMask(GLboolean flag);
-            void setGLClearDepthf(GLclampf depth);
-            void setGLColorMask(bool red, bool green, bool blue, bool alpha);
-            void setGLLightf(GLenum light, GLenum name, GLfloat param);
-            void setGLLightfv(GLenum light, GLenum name, const GLfloat *param);
 
         public:
             // Default constructor / destructor
              RenderSystem
              */
             void setScissorTest(bool enabled, size_t left = 0, size_t top = 0, size_t right = 800, size_t bottom = 600);
-        
-            void _setDiscardBuffers(unsigned int flags) { mDiscardBuffers = flags; }
-            unsigned int getDiscardBuffers(void) { return mDiscardBuffers; }
 
             void clearFrameBuffer(unsigned int buffers,
                 const ColourValue& colour = ColourValue::Black,
 			/// @copydoc RenderSystem::getDisplayMonitorCount
 			unsigned int getDisplayMonitorCount() const;
 
-            GLenum _getPolygonMode(void) { return mPolygonMode; }
-
             /// Internal method for anisotropy validation
             GLfloat _getCurrentAnisotropy(size_t unit);
 

RenderSystems/GLES/include/OgreGLESStateCacheManager.h

+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2012 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef __GLESStateCacheManager_H__
+#define __GLESStateCacheManager_H__
+
+#include "OgreGLESPrerequisites.h"
+
+typedef Ogre::GeneralAllocatedObject StateCacheAlloc;
+
+namespace Ogre
+{
+    class GLESStateCacheManagerImp;
+    
+    /** An in memory cache of the OpenGL ES state.
+     @remarks
+     State changes can be particularly expensive time wise. This is because
+     a change requires OpenGL to re-evaluate and update the state machine.
+     Because of the general purpose nature of OGRE we often set the state for
+     a specific texture, material, buffer, etc. But this may be the same as the
+     current status of the state machine and is therefore redundant and causes
+     unnecessary work to be performed by OpenGL.
+     @par
+     Instead we are caching the state so that we can check whether it actually
+     does need to be updated. This leads to improved performance all around and
+     can be somewhat dramatic in some cases.
+     */
+    class _OgreGLESExport GLESStateCacheManager : public StateCacheAlloc
+    {
+    private:
+        GLESStateCacheManagerImp* mImp;
+        
+    public:
+        GLESStateCacheManager(void);
+        ~GLESStateCacheManager(void);
+        
+        /** Initialize our cache variables and sets the
+            GL states on the current context.
+         */
+        void initializeCache();
+        
+        /** Clears all cached values
+         */
+        void clearCache();
+        
+		/** Bind an OpenGL buffer of any type.
+         @param target The buffer target.
+         @param buffer The buffer ID.
+         @param force Optional parameter to force an update.
+         */
+        void bindGLBuffer(GLenum target, GLuint buffer, GLenum attach = 0, bool force = false);
+        
+		/** Delete an OpenGL buffer of any type.
+         @param target The buffer target.
+         @param buffer The buffer ID.
+         @param force Optional parameter to force an update.
+         */
+        void deleteGLBuffer(GLenum target, GLuint buffer, GLenum attach = 0, bool force = false);
+        
+		/** Bind an OpenGL texture of any type.
+         @param target The texture target.
+         @param texture The texture ID.
+         */
+        void bindGLTexture(GLenum target, GLuint texture);
+        
+        /** Sets an integer parameter value per texture target.
+         @param target The texture target.
+         @param pname The parameter name.
+         @param param The parameter value.
+         */
+        void setTexParameteri(GLenum target, GLenum pname, GLint param);
+        
+        /** Activate an OpenGL texture unit.
+         @param offset The texture unit to activate.
+         @return Whether or not the texture unit was successfully activated.
+         */
+        bool activateGLTextureUnit(unsigned char unit);
+        
+        /** Gets the current blend equation setting.
+         @return The blend equation.
+         */
+        GLenum getBlendEquation(void) const;
+        
+        /** Sets the current blend equation setting.
+         @param eq The blend equation to use.
+         */
+        void setBlendEquation(GLenum eq);
+        
+        /** Sets the blending function.
+         @param source The blend mode for the source.
+         @param dest The blend mode for the destination
+         */
+        void setBlendFunc(GLenum source, GLenum dest);
+        
+        /** Gets the current depth mask setting.
+         @return The current depth mask.
+         */
+        GLboolean getDepthMask(void) const;
+        
+        /** Sets the current depth mask setting.
+         @param mask The depth mask to use.
+         */
+        void setDepthMask(GLboolean mask);
+        
+        /** Gets the current depth test function.
+         @return The current depth test function.
+         */
+        GLenum getDepthFunc(void) const;
+        
+        /** Sets the current depth test function.
+         @param func The depth test function to use.
+         */
+        void setDepthFunc(GLenum func);
+        
+		/** Gets the clear depth in the range from [0..1].
+         @return The current clearing depth.
+         */
+        GLclampf getClearDepth(void) const;
+        
+        /** Sets the clear depth in the range from [0..1].
+         @param depth The clear depth to use.
+         */
+        void setClearDepth(GLclampf depth);
+        
+        /** Sets the color to clear to.
+         @param red The red component.
+         @param green The green component.
+         @param blue The blue component.
+         @param alpha The alpha component.
+         */
+        void setClearColour(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+        
+        /** Gets the current colour mask setting.
+         @return An array containing the mask in RGBA order.
+         */
+        vector<GLboolean>::type & getColourMask(void) const;
+        
+        /** Sets the current colour mask.
+         @param red The red component.
+         @param green The green component.
+         @param blue The blue component.
+         @param alpha The alpha component.
+         */
+        void setColourMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+        
+        /** Gets the current stencil mask.
+         @return The stencil mask.
+         */
+        GLuint getStencilMask(void) const;
+        
+        /** Sets the stencil mask.
+         @param mask The stencil mask to use
+         */
+        void setStencilMask(GLuint mask);
+        
+        /** Enables a piece of OpenGL functionality.
+         @param flag The function to enable.
+         */
+        void setEnabled(GLenum flag);
+        
+        /** Disables a piece of OpenGL functionality.
+         @param flag The function to disable.
+         */
+        void setDisabled(GLenum flag);
+        
+        /** Gets the mask of buffers to be discarded if GL_EXT_discard_framebuffer is supported
+         @return The buffer mask.
+         */
+        unsigned int getDiscardBuffers(void) const;
+        
+        /** Sets the mask of buffers to be discarded if GL_EXT_discard_framebuffer is supported
+         @param flags The bit mask of buffers to be discarded. Stored as Ogre::FrameBufferType.
+         */
+        void setDiscardBuffers(unsigned int flags);
+        
+        /** Gets the current polygon rendering mode, fill, wireframe, points, etc.
+         @return The current polygon rendering mode.
+         */
+        GLenum getPolygonMode(void) const;
+        
+        /** Sets the current polygon rendering mode.
+         @param mode The polygon mode to use.
+         */
+        void setPolygonMode(GLenum mode);
+        
+        /** Sets the face culling mode.
+         @return The current face culling mode
+         */
+        GLenum getCullFace(void) const;
+        
+        /** Sets the face culling setting.
+         @param face The face culling mode to use.
+         */
+        void setCullFace(GLenum face);
+    };
+}
+
+#endif

RenderSystems/GLES/include/OgreGLESSupport.h

 {
     class GLESRenderSystem;
     class GLESPBuffer;
-
+    class GLESStateCacheManager;
+    
     class _OgreGLESExport GLESSupport
     {
         public:
-            GLESSupport() { }
+            GLESSupport() : mStateCacheMgr(0) { }
             virtual ~GLESSupport() { }
 
             /**
             {
                 return 1;
             }
-
+        
+            /**
+            * Get the state cache manager
+            */
+            GLESStateCacheManager* getStateCacheManager() const
+            {
+                return mStateCacheMgr;
+            }
+        
+            /**
+            * Set a valid state cache manager
+            */
+            void setStateCacheManager(GLESStateCacheManager* stateCacheMgr)
+            {
+                mStateCacheMgr = stateCacheMgr;
+            }
+        
             /**
             * Start anything special
             */
 
             // This contains the complete list of supported extensions
             std::set<String> extensionList;
+        
+            GLESStateCacheManager* mStateCacheMgr;
     };
 
 }

RenderSystems/GLES/src/EGL/Android/OgreAndroidEGLWindow.cpp

             EGL_GREEN_SIZE, 6,
             EGL_RED_SIZE, 5,
             EGL_DEPTH_SIZE, 16,
+            EGL_STENCIL_SIZE, 8,
             EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
             EGL_NONE
         };

RenderSystems/GLES/src/OgreGLESRenderSystem.cpp

 
 #include "OgreCamera.h"
 #include "OgreLight.h"
+#include "OgreGLESStateCacheManager.h"
 
 // Convenience macro from ARB_vertex_buffer_object spec
 #define VBO_BUFFER_OFFSET(i) ((char *)NULL + (i))
 
-// Copy this definition from desktop GL.  Used for polygon modes.
-#define GL_FILL    0x1B02
-
 namespace Ogre {
     GLESRenderSystem::GLESRenderSystem()
-        : mDepthWrite(true),
-          mStencilMask(0xFFFFFFFF),
-          mGpuProgramManager(0),
+        : mGpuProgramManager(0),
           mHardwareBufferManager(0),
-          mRTTManager(0),
-          mActiveTextureUnit(0)
+          mRTTManager(0)
     {
             // Get function pointers on platforms that doesn't have prototypes
 #ifndef GL_GLEXT_PROTOTYPES
             ::glUnmapBufferOES = (PFNGLUNMAPBUFFEROESPROC)eglGetProcAddress("glUnmapBufferOES");
 #endif
         GL_CHECK_ERROR;
-        size_t i;
-
 		LogManager::getSingleton().logMessage(getName() + " created.");
 
 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
         mResourceManager = OGRE_NEW AndroidResourceManager();
 #endif
+      
+        mStateCacheManager = new GLESStateCacheManager();
+        mGLSupport = getGLSupport();
+        mGLSupport->setStateCacheManager(mStateCacheManager);
         
-        mGLSupport = getGLSupport();
-
-        for (i = 0; i < MAX_LIGHTS; i++)
+        for (size_t i = 0; i < MAX_LIGHTS; i++)
+        {
             mLights[i] = NULL;
+        }
 
         mWorldMatrix = Matrix4::IDENTITY;
         mViewMatrix = Matrix4::IDENTITY;
-
         mGLSupport->addConfig();
 
-        mColourWrite[0] = mColourWrite[1] = mColourWrite[2] = mColourWrite[3] = true;
-
-        for (i = 0; i < OGRE_MAX_TEXTURE_LAYERS; i++)
+        for (size_t i = 0; i < OGRE_MAX_TEXTURE_LAYERS; i++)
         {
-            // Dummy value
-            mTextureCoordIndex[i] = 99;
+            mTextureCoordIndex[i] = 99; // Dummy value
         }
 
         mTextureCount = 0;
         mCurrentLights = 0;
         mMinFilter = FO_LINEAR;
         mMipFilter = FO_POINT;
-        mPolygonMode = GL_FILL;
     }
 
     GLESRenderSystem::~GLESRenderSystem()
 
         mRenderTargets.clear();
         OGRE_DELETE mGLSupport;
-    
+        delete mStateCacheManager;
+        
 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
         if (mResourceManager != NULL)
 		{
     void GLESRenderSystem::setNormaliseNormals(bool normalise)
     {
         if (normalise)
-            glEnable(GL_NORMALIZE);
+            mStateCacheManager->setEnabled(GL_NORMALIZE);
         else
-            glDisable(GL_NORMALIZE);
-
-        GL_CHECK_ERROR;
+            mStateCacheManager->setDisabled(GL_NORMALIZE);
     }
 
     void GLESRenderSystem::_useLights(const LightList& lights, unsigned short limit)
             {
                 gt = GL_EMISSION;
             }
-            glEnable(gt);
-            GL_CHECK_ERROR;
-            glEnable(GL_COLOR_MATERIAL);
-            GL_CHECK_ERROR;
+            mStateCacheManager->setEnabled(gt);
+            mStateCacheManager->setEnabled(GL_COLOR_MATERIAL);
         }
         else
         {
-             glDisable(GL_COLOR_MATERIAL);
+             mStateCacheManager->setDisabled(GL_COLOR_MATERIAL);
         }
 
         // XXX Cache previous values?
         GL_CHECK_ERROR;
         if (enabled)
         {
-            glEnable(GL_POINT_SPRITE_OES);
+            mStateCacheManager->setEnabled(GL_POINT_SPRITE_OES);
             GL_CHECK_ERROR;
         }
         else
         {
-            glDisable(GL_POINT_SPRITE_OES);
+            mStateCacheManager->setDisabled(GL_POINT_SPRITE_OES);
             GL_CHECK_ERROR;
         }
 
 		// Don't offer this as an option since D3D links it to sprite enabled
 		for (ushort i = 0; i < mFixedFunctionTextureUnits; ++i)
 		{
-			activateGLTextureUnit(i);
+			mStateCacheManager->activateGLTextureUnit(i);
 			glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, 
                       enabled ? GL_TRUE : GL_FALSE);
 		}
-		activateGLTextureUnit(0);
+		mStateCacheManager->activateGLTextureUnit(0);
     }
 
     void GLESRenderSystem::_setTexture(size_t stage, bool enabled, const TexturePtr &texPtr)
         // TODO We need control texture types?????
         GLESTexturePtr tex = texPtr;
 
-        if (!activateGLTextureUnit(stage))
+        if (!mStateCacheManager->activateGLTextureUnit(stage))
 			return;
 
         if (enabled)
                 // Note used
                 tex->touch();
                 glEnable(tex->getGLESTextureTarget());
+                mStateCacheManager->bindGLTexture(tex->getGLESTextureTarget(), tex->getGLID());
+                
             }
             else
-                glEnable(GL_TEXTURE_2D); // Assume 2D
-            GL_CHECK_ERROR;
-            
-            if (!tex.isNull())
-                glBindTexture(GL_TEXTURE_2D, tex->getGLID());
-            else
-                glBindTexture(GL_TEXTURE_2D, static_cast<GLESTextureManager*>(mTextureManager)->getWarningTextureID());
-            GL_CHECK_ERROR;
+            {
+                glEnable(GL_TEXTURE_2D);
+                mStateCacheManager->bindGLTexture(GL_TEXTURE_2D, static_cast<GLESTextureManager*>(mTextureManager)->getWarningTextureID());
+            }
         }
         else
         {
 
             // bind zero texture
             glBindTexture(GL_TEXTURE_2D, 0);
-            GL_CHECK_ERROR;
         }
 
-        activateGLTextureUnit(0);
+        mStateCacheManager->activateGLTextureUnit(0);
     }
 
     void GLESRenderSystem::_setTextureCoordSet(size_t stage, size_t index)
         // Default to no extra auto texture matrix
         mUseAutoTextureMatrix = false;
 
-        if (!activateGLTextureUnit(stage))
+        if (!mStateCacheManager->activateGLTextureUnit(stage))
             return;
         
         bool hasCubeMapExt = mCurrentCapabilities->hasCapability(RSC_CUBEMAPPING);
         {
             case TEXCALC_NONE:
                 if(hasCubeMapExt)
+                {
                     glDisable(GL_TEXTURE_GEN_STR_OES);
+                    GL_CHECK_ERROR
+                }
                 break;
 
             case TEXCALC_ENVIRONMENT_MAP:
                 {
                     glEnable(GL_TEXTURE_GEN_STR_OES);
                     glTexGeniOES( GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE_OES, GL_REFLECTION_MAP_OES );
-                    
+                    GL_CHECK_ERROR
                 }
                 mUseAutoTextureMatrix = true;
                 memset(mAutoTextureMatrix, 0, sizeof(GLfloat)*16);
                 {
                     glEnable(GL_TEXTURE_GEN_STR_OES);
                     glTexGeniOES( GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE_OES, GL_REFLECTION_MAP_OES );
-                
+                    GL_CHECK_ERROR
                 }
                 // We need an extra texture matrix here
                 // This sets the texture matrix to be the inverse of the view matrix
                 {
                     glEnable(GL_TEXTURE_GEN_STR_OES);
                     glTexGeniOES( GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE_OES, GL_NORMAL_MAP_OES );
-                    
+                    GL_CHECK_ERROR
                 }
                 break;
 
             default:
                 break;
         }
-
-		activateGLTextureUnit(0);
+		mStateCacheManager->activateGLTextureUnit(0);
     }
 
     void GLESRenderSystem::_setTextureBlendMode(size_t stage, const LayerBlendModeEx& bm)
                 cmd = 0;
         }
 
-		if (!activateGLTextureUnit(stage))
+		if (!mStateCacheManager->activateGLTextureUnit(stage))
 			return;
         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
         GL_CHECK_ERROR;
         if (bm.source2 == LBS_MANUAL)
             glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, cv2);
 
-		activateGLTextureUnit(0);
+		mStateCacheManager->activateGLTextureUnit(0);
     }
 
     GLint GLESRenderSystem::getTextureAddressingMode(TextureUnitState::TextureAddressingMode tam) const
 
     void GLESRenderSystem::_setTextureAddressingMode(size_t stage, const TextureUnitState::UVWAddressingMode& uvw)
     {
-		if (!activateGLTextureUnit(stage))
+		if (!mStateCacheManager->activateGLTextureUnit(stage))
 			return;
-        glTexParameteri(GL_TEXTURE_2D,
-                        GL_TEXTURE_WRAP_S, getTextureAddressingMode(uvw.u));
-        GL_CHECK_ERROR;
-        glTexParameteri(GL_TEXTURE_2D,
-                        GL_TEXTURE_WRAP_T, getTextureAddressingMode(uvw.v));
-        GL_CHECK_ERROR;
-		activateGLTextureUnit(0);
+        mStateCacheManager->setTexParameteri(GL_TEXTURE_2D,
+                                             GL_TEXTURE_WRAP_S, getTextureAddressingMode(uvw.u));
+        mStateCacheManager->setTexParameteri(GL_TEXTURE_2D,
+                                             GL_TEXTURE_WRAP_T, getTextureAddressingMode(uvw.v));
+		mStateCacheManager->activateGLTextureUnit(0);
     }
 
     void GLESRenderSystem::_setTextureBorderColour(size_t stage, const ColourValue& colour)
         if (mCurrentCapabilities->hasCapability(RSC_MIPMAP_LOD_BIAS))
         {
 #if GL_EXT_texture_lod_bias	// This extension only seems to be supported on iOS OS, block it out to fix Linux build
-            if (activateGLTextureUnit(unit))
+            if (mStateCacheManager->activateGLTextureUnit(unit))
             {
                 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, bias);
-                    activateGLTextureUnit(0);
+                    mStateCacheManager->activateGLTextureUnit(0);
             }
 #endif
         }
             return;
         }
 
-		if (!activateGLTextureUnit(stage))
+		if (!mStateCacheManager->activateGLTextureUnit(stage))
 			return;
 
         GLfloat mat[16];
 
         glMatrixMode(GL_MODELVIEW);
         GL_CHECK_ERROR;
-		activateGLTextureUnit(0);
+		mStateCacheManager->activateGLTextureUnit(0);
     }
 
     GLint GLESRenderSystem::getBlendMode(SceneBlendFactor ogreBlend) const
 		GLenum destBlend = getBlendMode(destFactor);
 		if(sourceFactor == SBF_ONE && destFactor == SBF_ZERO)
 		{
-			glDisable(GL_BLEND);
-			GL_CHECK_ERROR;
+			mStateCacheManager->setDisabled(GL_BLEND);
 		}
 		else
 		{
 			{
 				sourceBlend = getBlendMode(SBF_SOURCE_ALPHA);
 			}
-			glEnable(GL_BLEND);
-			GL_CHECK_ERROR;
-			glBlendFunc(sourceBlend, destBlend);
-			GL_CHECK_ERROR;
+            mStateCacheManager->setEnabled(GL_BLEND);
+            mStateCacheManager->setBlendFunc(sourceBlend, destBlend);
 		}
         
 #if GL_OES_blend_subtract
 #endif
 			break;
 		}
-		if (glBlendEquationOES)
-			glBlendEquationOES(func);
-        GL_CHECK_ERROR;
+        
+        mStateCacheManager->setBlendEquation(func);
 #endif
 	}
 
             if(sourceFactor == SBF_ONE && destFactor == SBF_ZERO && 
                sourceFactorAlpha == SBF_ONE && destFactorAlpha == SBF_ZERO)
             {
-                glDisable(GL_BLEND);
+                mStateCacheManager->setDisabled(GL_BLEND);
             }
             else
             {
-                glEnable(GL_BLEND);
-                GL_CHECK_ERROR;
+                mStateCacheManager->setEnabled(GL_BLEND);
+                
                 glBlendFuncSeparateOES(sourceBlend, destBlend, sourceBlendAlpha, destBlendAlpha);
                 GL_CHECK_ERROR;
             }
 		static bool lasta2c = false;
 		if (func == CMPF_ALWAYS_PASS)
 		{
-			glDisable(GL_ALPHA_TEST);
-			GL_CHECK_ERROR;
+            mStateCacheManager->setDisabled(GL_ALPHA_TEST);
 		}
 		else
 		{
-			glEnable(GL_ALPHA_TEST);
-			GL_CHECK_ERROR;
+            mStateCacheManager->setEnabled(GL_ALPHA_TEST);
 
 			a2c = alphaToCoverage;
 
 		if (a2c != lasta2c && getCapabilities()->hasCapability(RSC_ALPHA_TO_COVERAGE))
 		{
 			if (a2c)
-				glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+                mStateCacheManager->setEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
 			else
-				glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
-
-			GL_CHECK_ERROR;
+                mStateCacheManager->setDisabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
 
 			lasta2c = a2c;
 		} 
         switch( mode )
         {
             case CULL_NONE:
-                glDisable(GL_CULL_FACE);
-                GL_CHECK_ERROR;
+                mStateCacheManager->setDisabled(GL_CULL_FACE);
                 return;
 
             default:
                 break;
         }
 
-        glEnable(GL_CULL_FACE);
-        GL_CHECK_ERROR;
-        glCullFace(cullMode);
-        GL_CHECK_ERROR;
+        mStateCacheManager->setEnabled(GL_CULL_FACE);
+        mStateCacheManager->setCullFace(cullMode);
     }
 
     void GLESRenderSystem::_setDepthBufferParams(bool depthTest, bool depthWrite, CompareFunction depthFunction)
     {
         if (enabled)
         {
-            glClearDepthf(1.0f);
-            GL_CHECK_ERROR;
-            glEnable(GL_DEPTH_TEST);
-            GL_CHECK_ERROR;
+            mStateCacheManager->setClearDepth(1.0f);
+            mStateCacheManager->setEnabled(GL_DEPTH_TEST);
         }
         else
         {
-            glDisable(GL_DEPTH_TEST);
-            GL_CHECK_ERROR;
+            mStateCacheManager->setDisabled(GL_DEPTH_TEST);
         }
     }
 
     void GLESRenderSystem::_setDepthBufferWriteEnabled(bool enabled)
     {
-        GLboolean flag = enabled ? GL_TRUE : GL_FALSE;
-        glDepthMask(flag);
-        GL_CHECK_ERROR;
-
-        // Store for reference in _beginFrame
-        mDepthWrite = enabled;
+        mStateCacheManager->setDepthMask(enabled ? GL_TRUE : GL_FALSE);
     }
 
     void GLESRenderSystem::_setDepthBufferFunction(CompareFunction func)
     {
-        glDepthFunc(convertCompareFunction(func));
-        GL_CHECK_ERROR;
+        mStateCacheManager->setDepthFunc(convertCompareFunction(func));
     }
 
     void GLESRenderSystem::_setDepthBias(float constantBias, float slopeScaleBias)
     {
         if (constantBias != 0 || slopeScaleBias != 0)
         {
-            glEnable(GL_POLYGON_OFFSET_FILL);
-            GL_CHECK_ERROR;
+            mStateCacheManager->setEnabled(GL_POLYGON_OFFSET_FILL);
             glPolygonOffset(-slopeScaleBias, -constantBias);
             GL_CHECK_ERROR;
         }
         else
         {
-            glDisable(GL_POLYGON_OFFSET_FILL);
-            GL_CHECK_ERROR;
+            mStateCacheManager->setDisabled(GL_POLYGON_OFFSET_FILL);
         }
     }
 
     void GLESRenderSystem::_setColourBufferWriteEnabled(bool red, bool green, bool blue, bool alpha)
     {
-        glColorMask(red, green, blue, alpha);
-        GL_CHECK_ERROR;
-
-        // record this
-        mColourWrite[0] = red;
-        mColourWrite[1] = blue;
-        mColourWrite[2] = green;
-        mColourWrite[3] = alpha;
+        mStateCacheManager->setColourMask(red, green, blue, alpha);
     }
 
     void GLESRenderSystem::_setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
                 break;
             default:
                 // Give up on it
-                glDisable(GL_FOG);
-                GL_CHECK_ERROR;
+                mStateCacheManager->setDisabled(GL_FOG);
                 return;
         }
 
-        glEnable(GL_FOG);
-        GL_CHECK_ERROR;
+        mStateCacheManager->setEnabled(GL_FOG);
         glFogf(GL_FOG_MODE, fogMode);
         GLfloat fogColor[4] = { colour.r, colour.g, colour.b, colour.a };
         glFogfv(GL_FOG_COLOR, fogColor);
         switch(level)
         {
         case PM_POINTS:
-            mPolygonMode = GL_POINTS;
+            mStateCacheManager->setPolygonMode(GL_POINTS);
             break;
         case PM_WIREFRAME:
-            mPolygonMode = GL_LINE_STRIP;
+            mStateCacheManager->setPolygonMode(GL_LINE_STRIP);
             break;
         default:
         case PM_SOLID:
-            mPolygonMode = GL_FILL;
+            mStateCacheManager->setPolygonMode(GL_FILL);
             break;
         }
     }
     {
         if (enabled)
         {
-            glEnable(GL_STENCIL_TEST);
+            mStateCacheManager->setEnabled(GL_STENCIL_TEST);
         }
         else
         {
-            glDisable(GL_STENCIL_TEST);
+            mStateCacheManager->setDisabled(GL_STENCIL_TEST);
         }
     }
 
                                                 StencilOperation passOp,
                                                 bool twoSidedOperation)
     {
-		mStencilMask = mask;
-
-        glStencilMask(mask);
+        mStateCacheManager->setStencilMask(mask);
         glStencilFunc(convertCompareFunction(func), refValue, mask);
         glStencilOp(
             convertStencilOp(stencilFailOp, false),
 
     void GLESRenderSystem::_setTextureUnitFiltering(size_t unit, FilterType ftype, FilterOptions fo)
     {
-		if (!activateGLTextureUnit(unit))
+		if (!mStateCacheManager->activateGLTextureUnit(unit))
 			return;
 
         switch (ftype)
                 mMinFilter = fo;
 
                 // Combine with existing mip filter
-                glTexParameteri(GL_TEXTURE_2D,
-                                GL_TEXTURE_MIN_FILTER,
-                                getCombinedMinMipFilter());
-                GL_CHECK_ERROR;
+                mStateCacheManager->setTexParameteri(GL_TEXTURE_2D,
+                                                     GL_TEXTURE_MIN_FILTER,
+                                                     getCombinedMinMipFilter());
                 break;
 
             case FT_MAG:
                 {
                     case FO_ANISOTROPIC: // GL treats linear and aniso the same
                     case FO_LINEAR:
-                        glTexParameteri(GL_TEXTURE_2D,
-                                        GL_TEXTURE_MAG_FILTER,
-                                        GL_LINEAR);
-                        GL_CHECK_ERROR;
+                        mStateCacheManager->setTexParameteri(GL_TEXTURE_2D,
+                                                             GL_TEXTURE_MAG_FILTER,
+                                                             GL_LINEAR);
                         break;
                     case FO_POINT:
                     case FO_NONE:
-                        glTexParameteri(GL_TEXTURE_2D,
-                                        GL_TEXTURE_MAG_FILTER,
-                                        GL_NEAREST);
-                        GL_CHECK_ERROR;
+                        mStateCacheManager->setTexParameteri(GL_TEXTURE_2D,
+                                                             GL_TEXTURE_MAG_FILTER,
+                                                             GL_NEAREST);
                         break;
                 }
                 break;
                 mMipFilter = fo;
 
                 // Combine with existing min filter
-                glTexParameteri(GL_TEXTURE_2D,
-                                GL_TEXTURE_MIN_FILTER,
-                                getCombinedMinMipFilter());
-                GL_CHECK_ERROR;
+                mStateCacheManager->setTexParameteri(GL_TEXTURE_2D,
+                                                     GL_TEXTURE_MIN_FILTER,
+                                                     getCombinedMinMipFilter());
                 break;
         }
 
-		activateGLTextureUnit(0);
+		mStateCacheManager->activateGLTextureUnit(0);
     }
 
     GLfloat GLESRenderSystem::_getCurrentAnisotropy(size_t unit)
 		if (!mCurrentCapabilities->hasCapability(RSC_ANISOTROPY))
 			return;
 
-		if (!activateGLTextureUnit(unit))
+		if (!mStateCacheManager->activateGLTextureUnit(unit))
 			return;
 
 		GLfloat largest_supported_anisotropy = 0;
 		if (_getCurrentAnisotropy(unit) != maxAnisotropy)
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
 
-		activateGLTextureUnit(0);
+		mStateCacheManager->activateGLTextureUnit(0);
     }
 
     void GLESRenderSystem::setVertexDeclaration(VertexDeclaration* decl)
                 op.vertexData->vertexBufferBinding->getBuffer(elem->getSource());
             if (mCurrentCapabilities->hasCapability(RSC_VBO))
             {
-                glBindBuffer(GL_ARRAY_BUFFER,
-                    static_cast<const GLESHardwareVertexBuffer*>(vertexBuffer.get())->getGLBufferId());
-                GL_CHECK_ERROR;
+                mStateCacheManager->bindGLBuffer(GL_ARRAY_BUFFER,
+                    static_cast<const GLESHardwareVertexBuffer*>(vertexBuffer.get())->getGLBufferId(), true);
                 pBufferData = VBO_BUFFER_OFFSET(elem->getOffset());
             }
             else
             }
 
             VertexElementSemantic sem = elem->getSemantic();
-
             {
                 GL_CHECK_ERROR;
                 // fixed-function & builtin attribute support
                 break;
         }
 
+        GLenum polyMode = mStateCacheManager->getPolygonMode();
         if (op.useIndexes)
         {
             if(mCurrentCapabilities->hasCapability(RSC_VBO))
             {
-                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
-                             static_cast<GLESHardwareIndexBuffer*>(op.indexData->indexBuffer.get())->getGLBufferId());
+                mStateCacheManager->bindGLBuffer(GL_ELEMENT_ARRAY_BUFFER,
+                             static_cast<GLESHardwareIndexBuffer*>(op.indexData->indexBuffer.get())->getGLBufferId(), true);
 
-                GL_CHECK_ERROR;
                 pBufferData = VBO_BUFFER_OFFSET(op.indexData->indexStart *
                                                 op.indexData->indexBuffer->getIndexSize());
             }
                                   mDerivedDepthBiasMultiplier * mCurrentPassIterationNum,
                                   mDerivedDepthBiasSlopeScale);
                 }
-				GL_CHECK_ERROR;
-                glDrawElements((_getPolygonMode() == GL_FILL) ? primType : _getPolygonMode(), op.indexData->indexCount, indexType, pBufferData);
+                
+                
+                glDrawElements((polyMode == GL_FILL) ? primType : polyMode, op.indexData->indexCount, indexType, pBufferData);
                 GL_CHECK_ERROR;
             } while (updatePassIterationRenderState());
         }
                                   mDerivedDepthBiasMultiplier * mCurrentPassIterationNum,
                                   mDerivedDepthBiasSlopeScale);
                 }
-                glDrawArrays((_getPolygonMode() == GL_FILL) ? primType : _getPolygonMode(), 0, op.vertexData->vertexCount);
+                glDrawArrays((polyMode == GL_FILL) ? primType : polyMode, 0, op.vertexData->vertexCount);
                 GL_CHECK_ERROR;
             } while (updatePassIterationRenderState());
         }
 
         if (enabled)
         {
-            glEnable(GL_SCISSOR_TEST);
+            mStateCacheManager->setEnabled(GL_SCISSOR_TEST);
             // NB GL uses width / height rather than right / bottom
             x = left;
             if (flipping)
         }
         else
         {
-            glDisable(GL_SCISSOR_TEST);
+            mStateCacheManager->setDisabled(GL_SCISSOR_TEST);
             // GL requires you to reset the scissor when disabling
             w = mActiveViewport->getActualWidth();
             h = mActiveViewport->getActualHeight();
                                             const ColourValue& colour,
                                             Real depth, unsigned short stencil)
     {
-        bool colourMask = !mColourWrite[0] || !mColourWrite[1] ||
-                          !mColourWrite[2] || !mColourWrite[3];
+        GLboolean* colourWrite = &mStateCacheManager->getColourMask()[0];
+        bool colourMask = !colourWrite[0] || !colourWrite[1] ||
+                          !colourWrite[2] || !colourWrite[3];
+        GLuint stencilMask = mStateCacheManager->getStencilMask();
 
         GLbitfield flags = 0;
         if (buffers & FBT_COLOUR)
 			// Enable buffer for writing if it isn't
             if (colourMask)
             {
-                glColorMask(true, true, true, true);
-                GL_CHECK_ERROR;
+                mStateCacheManager->setColourMask(true, true, true, true);
             }
-            glClearColor(colour.r, colour.g, colour.b, colour.a);
-            GL_CHECK_ERROR;
+            mStateCacheManager->setClearColour(colour.r, colour.g, colour.b, colour.a);
         }
         if (buffers & FBT_DEPTH)
         {
             flags |= GL_DEPTH_BUFFER_BIT;
 			// Enable buffer for writing if it isn't
-            if (!mDepthWrite)
+            if (!mStateCacheManager->getDepthMask())
             {
-                glDepthMask(GL_TRUE);
-                GL_CHECK_ERROR;
+                mStateCacheManager->setDepthMask(GL_TRUE);
             }
-            glClearDepthf(depth);
-            GL_CHECK_ERROR;
+            mStateCacheManager->setClearDepth(depth);
         }
         if (buffers & FBT_STENCIL)
         {
             flags |= GL_STENCIL_BUFFER_BIT;
 			// Enable buffer for writing if it isn't
-            glStencilMask(0xFFFFFFFF);
-            GL_CHECK_ERROR;
+            mStateCacheManager->setStencilMask(0xFFFFFFFF);
             glClearStencil(stencil);
             GL_CHECK_ERROR;
         }
 
 		// Should be enable scissor test due the clear region is
 		// relied on scissor box bounds.
-        GLboolean scissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST);
-        GL_CHECK_ERROR;
-        if (!scissorTestEnabled)
-        {
-            glEnable(GL_SCISSOR_TEST);
-            GL_CHECK_ERROR;
-        }
+        mStateCacheManager->setEnabled(GL_SCISSOR_TEST);
 
 		// Sets the scissor box as same as viewport
         GLint viewport[4], scissor[4];
             GL_CHECK_ERROR;
         }
 
-        _setDiscardBuffers(buffers);
+        mStateCacheManager->setDiscardBuffers(buffers);
 
 		// Clear buffers
         glClear(flags);
         }
 
         // Restore scissor test
-        if (!scissorTestEnabled)
-        {
-            glDisable(GL_SCISSOR_TEST);
-            GL_CHECK_ERROR;
-        }
+        mStateCacheManager->setDisabled(GL_SCISSOR_TEST);
 
         // Reset buffer write state
-        if (!mDepthWrite && (buffers & FBT_DEPTH))
+        if (!mStateCacheManager->getDepthMask() && (buffers & FBT_DEPTH))
         {
-            glDepthMask(GL_FALSE);
-            GL_CHECK_ERROR;
+            mStateCacheManager->setDepthMask(GL_FALSE);
         }
 
         if (colourMask && (buffers & FBT_COLOUR))
         {
-            glColorMask(mColourWrite[0], mColourWrite[1], mColourWrite[2], mColourWrite[3]);
-            GL_CHECK_ERROR;
+            mStateCacheManager->setColourMask(colourWrite[0], colourWrite[1], colourWrite[2], colourWrite[3]);
         }
 
         if (buffers & FBT_STENCIL)
         {
-            glStencilMask(mStencilMask);
-            GL_CHECK_ERROR;
+            mStateCacheManager->setStencilMask(stencilMask);
         }
     }
 
         // Must reset depth/colour write mask to according with user desired, otherwise,
         // clearFrameBuffer would be wrong because the value we are recorded may be
         // difference with the really state stored in GL context.
-        glDepthMask(mDepthWrite);
-        glColorMask(mColourWrite[0], mColourWrite[1], mColourWrite[2], mColourWrite[3]);
-        glStencilMask(mStencilMask);
+        glDepthMask(mStateCacheManager->getDepthMask());
+        GLboolean* colourWrite = &mStateCacheManager->getColourMask()[0];
+        glColorMask(colourWrite[0], colourWrite[1], colourWrite[2], colourWrite[3]);
+        glStencilMask(mStateCacheManager->getStencilMask());
     }
 
     void GLESRenderSystem::_unregisterContext(GLESContext *context)
 
     void GLESRenderSystem::_oneTimeContextInitialization()
     {
-        glDisable(GL_DITHER);
-        GL_CHECK_ERROR;
+        mStateCacheManager->initializeCache();
+        mStateCacheManager->setDisabled(GL_DITHER);
 
         int fsaa_active = false;
         glGetIntegerv(GL_SAMPLE_BUFFERS,(GLint*)&fsaa_active);
 		return 1;
 	}
     
-    bool GLESRenderSystem::activateGLTextureUnit(size_t unit)
-	{
-		if (mActiveTextureUnit != unit)
-		{
-			if (unit < getCapabilities()->getNumTextureUnits())
-			{
-				glActiveTexture(GL_TEXTURE0 + unit);
-                GL_CHECK_ERROR;
-				mActiveTextureUnit = unit;
-				return true;
-			}
-			else if (!unit)
-			{
-				// always ok to use the first unit
-				return true;
-			}
-			else
-			{
-				return false;
-			}
-		}
-		else
-		{
-			return true;
-		}
-	}
 	//---------------------------------------------------------------------
 #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
     void GLESRenderSystem::resetRenderer(RenderWindow* win)
         LogManager::getSingleton().logMessage("*** OpenGL ES 1.x Reset Renderer Started ***");
         LogManager::getSingleton().logMessage("********************************************");
         
+        mStateCacheManager->clearCache();
         initialiseContext(win);
         
         mGLSupport->initialiseExtensions();

RenderSystems/GLES/src/OgreGLESStateCacheManager.cpp

+/*
+ -----------------------------------------------------------------------------
+ This source file is part of OGRE
+ (Object-oriented Graphics Rendering Engine)
+ For the latest info, see http://www.ogre3d.org/
+ 
+ Copyright (c) 2000-2012 Torus Knot Software Ltd
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ -----------------------------------------------------------------------------
+ */
+
+#include "OgreStableHeaders.h"
+#include "OgreGLESStateCacheManager.h"
+#include "OgreGLESRenderSystem.h"
+#include "OgreLogManager.h"
+#include "OgreRoot.h"
+
+#if OGRE_NO_GLES_STATE_CACHE_SUPPORT == 0
+#   include "OgreGLESStateCacheManagerImp.h"
+#else
+#   include "OgreGLESNullStateCacheManagerImp.h"
+#endif
+
+namespace Ogre {
+    
+    GLESStateCacheManager::GLESStateCacheManager() 
+    {
+        mImp = new GLESStateCacheManagerImp();
+    }
+    
+    GLESStateCacheManager::~GLESStateCacheManager()
+    {
+        delete mImp;
+    }
+
+    void GLESStateCacheManager::initializeCache()
+    {
+        mImp->initializeCache();
+    }
+    
+    void GLESStateCacheManager::clearCache()
+    {
+        mImp->clearCache();
+    }
+    
+    void GLESStateCacheManager::bindGLBuffer(GLenum target, GLuint buffer, GLenum attach, bool force)
+    {
+        mImp->bindGLBuffer(target, buffer, attach, force);
+    }
+    
+    void GLESStateCacheManager::deleteGLBuffer(GLenum target, GLuint buffer, GLenum attach, bool force)
+    {
+        mImp->deleteGLBuffer(target, buffer, attach, force);
+    }
+    
+    void GLESStateCacheManager::setTexParameteri(GLenum target, GLenum pname, GLint param)
+    {
+        mImp->setTexParameteri(target, pname, param);
+    }
+    
+    void GLESStateCacheManager::bindGLTexture(GLenum target, GLuint texture)
+    {
+        mImp->bindGLTexture(target, texture);
+    }
+    
+    bool GLESStateCacheManager::activateGLTextureUnit(unsigned char unit)
+	{
+        mImp->activateGLTextureUnit(unit);
+	}
+    
+    void GLESStateCacheManager::setBlendFunc(GLenum source, GLenum dest)
+    {
+        mImp->setBlendFunc(source, dest);
+    }
+    
+    void GLESStateCacheManager::setBlendEquation(GLenum eq)
+    {
+        mImp->setBlendEquation(eq);
+    }
+    
+    void GLESStateCacheManager::setDepthMask(GLboolean mask)
+    {
+        mImp->setDepthMask(mask);
+    }
+    
+    void GLESStateCacheManager::setDepthFunc(GLenum func)
+    {
+        mImp->setDepthFunc(func);
+    }
+    
+    void GLESStateCacheManager::setClearDepth(GLclampf depth)
+    {
+        mImp->setClearDepth(depth);
+    }
+    
+    void GLESStateCacheManager::setClearColour(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+    {
+        mImp->setClearColour(red, green, blue, alpha);
+    }
+    
+    void GLESStateCacheManager::setColourMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+    {
+        mImp->setColourMask(red, green, blue, alpha);
+    }
+    
+    void GLESStateCacheManager::setStencilMask(GLuint mask)
+    {
+        mImp->setStencilMask(mask);
+    }
+    
+    void GLESStateCacheManager::setEnabled(GLenum flag)
+    {
+        mImp->setEnabled(flag);
+    }
+    
+    void GLESStateCacheManager::setDisabled(GLenum flag)
+    {
+        mImp->setDisabled(flag);
+    }
+    
+    void GLESStateCacheManager::setCullFace(GLenum face)
+    {
+        mImp->setCullFace(face);
+    }
+    
+    GLenum GLESStateCacheManager::getBlendEquation() const
+    {
+        return mImp->getBlendEquation();
+    }
+    
+    GLboolean GLESStateCacheManager::getDepthMask() const
+    {
+        return mImp->getDepthMask();
+    }
+    
+    GLenum GLESStateCacheManager::getDepthFunc() const
+    {
+        return mImp->getDepthFunc();
+    }
+    
+    GLclampf GLESStateCacheManager::getClearDepth() const
+    {
+        return mImp->getClearDepth();
+    }
+    
+    vector<GLboolean>::type & GLESStateCacheManager::getColourMask() const
+    {
+        return mImp->getColourMask();
+    }
+    
+    GLuint GLESStateCacheManager::getStencilMask() const
+    {
+        return mImp->getStencilMask();
+    }
+    
+    unsigned int GLESStateCacheManager::getDiscardBuffers() const
+    {
+        return mImp->getDiscardBuffers();
+    }
+    
+    void GLESStateCacheManager::setDiscardBuffers(unsigned int flags)
+    {
+        mImp->setDiscardBuffers(flags);
+    }
+    
+    GLenum GLESStateCacheManager::getPolygonMode() const
+    {
+        return mImp->getPolygonMode();
+    }
+    
+    void GLESStateCacheManager::setPolygonMode(GLenum mode)
+    {
+        mImp->setPolygonMode(mode);
+    }
+    
+    GLenum GLESStateCacheManager::getCullFace() const
+    {
+        return mImp->getCullFace();
+    }
+}

RenderSystems/GLES/src/OgreGLESTexture.cpp

 #include "OgreGLESPixelFormat.h"
 #include "OgreGLESRenderSystem.h"
 #include "OgreGLESHardwarePixelBuffer.h"
-
+#include "OgreGLESStateCacheManager.h"
 #include "OgreRoot.h"
 
 namespace Ogre {
         GL_CHECK_ERROR;
         
 		// Set texture type
-        glBindTexture(getGLESTextureTarget(), mTextureID);
-        GL_CHECK_ERROR;
+        mGLSupport.getStateCacheManager()->bindGLTexture(getGLESTextureTarget(), mTextureID);
         
         // Set some misc default parameters, these can of course be changed later
-        glTexParameteri(getGLESTextureTarget(),
-                        GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
-        GL_CHECK_ERROR;
-        glTexParameteri(getGLESTextureTarget(),
-                        GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        GL_CHECK_ERROR;
-        glTexParameteri(getGLESTextureTarget(),
-                        GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        GL_CHECK_ERROR;
-        glTexParameteri(getGLESTextureTarget(),
-                        GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-        GL_CHECK_ERROR;
+        mGLSupport.getStateCacheManager()->setTexParameteri(getGLESTextureTarget(),
+                                                             GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+
+        mGLSupport.getStateCacheManager()->setTexParameteri(getGLESTextureTarget(),
+                                                             GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+        mGLSupport.getStateCacheManager()->setTexParameteri(getGLESTextureTarget(),
+                                                             GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        
+        mGLSupport.getStateCacheManager()->setTexParameteri(getGLESTextureTarget(),
+                                                             GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
         
 		// If we can do automip generation and the user desires this, do so
         mMipmapsHardwareGenerated =

RenderSystems/GLES/src/StateCacheManager/OgreGLESNullStateCacheManagerImp.cpp

+/*
+ -----------------------------------------------------------------------------
+ This source file is part of OGRE
+ (Object-oriented Graphics Rendering Engine)
+ For the latest info, see http://www.ogre3d.org/
+ 
+ Copyright (c) 2000-2012 Torus Knot Software Ltd
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ -----------------------------------------------------------------------------
+ */
+
+#include "OgreStableHeaders.h"
+#include "OgreGLESNullStateCacheManagerImp.h"
+#include "OgreGLESRenderSystem.h"
+#include "OgreLogManager.h"
+#include "OgreRoot.h"
+
+namespace Ogre {
+    
+    GLESStateCacheManagerImp::GLESStateCacheManagerImp(void) 
+    {
+        clearCache();
+    }
+    
+    GLESStateCacheManagerImp::~GLESStateCacheManagerImp(void)
+    {
+    }
+    
+    void GLESStateCacheManagerImp::initializeCache()
+    {
+        glBlendEquationOES(GL_FUNC_ADD_OES);
+        GL_CHECK_ERROR
+        
+        glBlendFunc(GL_ONE, GL_ZERO);
+        GL_CHECK_ERROR
+        
+        glCullFace(mCullFace);
+        GL_CHECK_ERROR
+        
+        glDepthFunc(mDepthFunc);
+        GL_CHECK_ERROR
+        
+        glDepthMask(mDepthMask);
+        GL_CHECK_ERROR
+        
+        glStencilMask(mStencilMask);
+        GL_CHECK_ERROR
+        
+        glClearDepthf(mClearDepth);
+        GL_CHECK_ERROR
+        
+        glBindTexture(GL_TEXTURE_2D, 0);
+        GL_CHECK_ERROR
+        
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+        GL_CHECK_ERROR
+        
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+        GL_CHECK_ERROR
+        
+        glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
+        GL_CHECK_ERROR
+        
+        glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
+        GL_CHECK_ERROR
+        
+        glActiveTexture(GL_TEXTURE0);
+        GL_CHECK_ERROR
+        
+        glClearColor(mClearColour[0], mClearColour[1], mClearColour[2], mClearColour[3]);
+        GL_CHECK_ERROR
+        
+        glColorMask(mColourMask[0], mColourMask[1], mColourMask[2], mColourMask[3]);
+        GL_CHECK_ERROR
+    }
+    
+    void GLESStateCacheManagerImp::clearCache()
+    {
+        mDepthMask = GL_TRUE;
+        mPolygonMode = GL_FILL;
+        mBlendEquation = GL_FUNC_ADD_OES;
+        mCullFace = GL_BACK;
+        mDepthFunc = GL_LESS;
+        mStencilMask = 0xFFFFFFFF;
+        mActiveTextureUnit = 0;
+        mDiscardBuffers = 0;
+        mClearDepth = 1.0f;
+        
+        mClearColour.reserve(4);
+        mClearColour[0] = mClearColour[1] = mClearColour[2] = mClearColour[3] = 0.0f;
+        
+        mColourMask.reserve(4);
+        mColourMask[0] = mColourMask[1] = mColourMask[2] = mColourMask[3] = GL_TRUE;
+    }
+    
+    void GLESStateCacheManagerImp::bindGLBuffer(GLenum target, GLuint buffer, GLenum attach, bool force)
+    {
+        // Update GL
+        if(target == GL_FRAMEBUFFER_OES)
+            glBindFramebufferOES(target, buffer);
+        else if(target == GL_RENDERBUFFER_OES)
+            glBindRenderbufferOES(target, buffer);
+        else
+            glBindBuffer(target, buffer);
+        
+        GL_CHECK_ERROR
+    }
+    
+    void GLESStateCacheManagerImp::deleteGLBuffer(GLenum target, GLuint buffer, GLenum attach, bool force)
+    {
+        // Buffer name 0 is reserved and we should never try to delete it
+        if(buffer == 0)
+            return;
+        
+        if(target == GL_FRAMEBUFFER_OES)
+            glDeleteFramebuffersOES(1, &buffer);
+        else if(target == GL_RENDERBUFFER_OES)
+            glDeleteRenderbuffersOES(1, &buffer);
+        else
+            glDeleteBuffers(1, &buffer);
+        
+        GL_CHECK_ERROR
+    }
+    
+    void GLESStateCacheManagerImp::setTexParameteri(GLenum target, GLenum pname, GLint param)
+    {
+        // Update GL
+        glTexParameteri(target, pname, param);
+        GL_CHECK_ERROR
+    }
+    
+
+    void GLESStateCacheManagerImp::bindGLTexture(GLenum target, GLuint texture)
+    {
+        // Update GL
+        glBindTexture(target, texture);
+        GL_CHECK_ERROR
+    }
+    
+    bool GLESStateCacheManagerImp::activateGLTextureUnit(unsigned char unit)
+	{
+        // Always return true for the currently bound texture unit
+        if (mActiveTextureUnit == unit)
+            return true;
+        
+        if (unit < dynamic_cast<GLESRenderSystem*>(Root::getSingleton().getRenderSystem())->getCapabilities()->getNumTextureUnits())
+        {
+            glActiveTexture(GL_TEXTURE0 + unit);
+            GL_CHECK_ERROR
+            
+            mActiveTextureUnit = unit;
+            
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+	}
+    
+    void GLESStateCacheManagerImp::setBlendFunc(GLenum source, GLenum dest)
+    {
+        glBlendFunc(source, dest);
+        GL_CHECK_ERROR
+    }
+    
+    void GLESStateCacheManagerImp::setBlendEquation(GLenum eq)
+    {
+        mBlendEquation = eq;
+        glBlendEquationOES(eq);
+        GL_CHECK_ERROR
+    }
+    
+    void GLESStateCacheManagerImp::setDepthMask(GLboolean mask)
+    {
+        if(mDepthMask != mask)
+        {
+            mDepthMask = mask;
+            
+            glDepthMask(mask);
+            GL_CHECK_ERROR
+        }
+    }
+    
+    void GLESStateCacheManagerImp::setDepthFunc(GLenum func)
+    {
+        if(mDepthFunc != func)
+        {
+            mDepthFunc = func;
+            
+            glDepthFunc(func);
+            GL_CHECK_ERROR
+        }
+    }