Remove RenderSurface from Core
[platform/core/uifw/dali-core.git] / dali / internal / render / gl-resources / context.h
index 073a2a0..be2db89 100644 (file)
@@ -1,8 +1,8 @@
-#ifndef __DALI_INTERNAL_CONTEXT_H__
-#define __DALI_INTERNAL_CONTEXT_H__
+#ifndef DALI_INTERNAL_CONTEXT_H
+#define DALI_INTERNAL_CONTEXT_H
 
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 
 // INTERNAL INCLUDES
-#include <dali/integration-api/gl-defines.h>
-#include <dali/public-api/common/map-wrapper.h>
-#include <dali/public-api/common/vector-wrapper.h>
-#include <dali/public-api/actors/renderable-actor.h>
-#include <dali/integration-api/debug.h>
-#include <dali/integration-api/gl-abstraction.h>
-#include <dali/internal/render/common/performance-monitor.h>
+#include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/common/dali-common.h>
 #include <dali/public-api/math/rect.h>
 #include <dali/public-api/math/vector4.h>
+#include <dali/public-api/rendering/renderer.h>
+#include <dali/devel-api/common/owner-container.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/integration-api/gl-defines.h>
+#include <dali/internal/render/common/performance-monitor.h>
+#include <dali/internal/render/gl-resources/texture-units.h>
+#include <dali/internal/render/gl-resources/frame-buffer-state-cache.h>
+#include <dali/internal/render/gl-resources/gl-call-debug.h>
 
 namespace Dali
 {
@@ -36,21 +39,6 @@ namespace Dali
 namespace Internal
 {
 
-class Program; // to be able to cache programs
-
-// wrap gl calls with CHECK_GL eg "CHECK_GL( *this, glBindTexture(textureId) );"
-// will LOG any glErrors eg "glError (0x0501) GL_INVALID_VALUE - glBindTexture(textureId)"
-// only enable if specifically enabled as it slows down GL a lot!
-#ifdef DALI_GL_ERROR_CHECK
-#define CHECK_GL(c,a)  (a); (c).CheckGlError(#a)
-#else
-#define CHECK_GL(c,a)  (a)
-#endif
-
-// Don't put guards around here (LOG_INFO has it's own guards)
-#define LOG_GL(format, args...) \
-  DALI_LOG_INFO(Context::gGlLogFilter, Debug::General, format, ## args)
-
 /**
  * Context records the current GL state, and provides access to the OpenGL ES 2.0 API.
  * Context avoids duplicate GL calls, if the same setting etc. is requested repeatedly.
@@ -58,14 +46,26 @@ class Program; // to be able to cache programs
 class Context
 {
 public:
+
+  /**
+   * FrameBuffer Clear mode
+   */
+  enum ClearMode
+  {
+    FORCE_CLEAR,        ///< always perform the glClear regardless of current state
+    CHECK_CACHED_VALUES ///< check the Frame buffers cached state to see if a clear is required
+  };
+
   /**
    * Size of the VertexAttributeArray enables
    * GLES specification states that there's minimum of 8
    */
   static const unsigned int MAX_ATTRIBUTE_CACHE_SIZE = 8;
 
+  static const unsigned int MAX_TEXTURE_UNITS = 8; // for GLES 2.0 8 is guaranteed, which is more than DALi uses anyways
+
   /**
-   * Creates the Dali Context object.
+   * Creates the Dali Context object for surface rendering only.
    * This method does not create an OpenGL context i.e. that is done from outside dali-core.
    * @pre Context has not been created.
    * @exception Context already created.
@@ -74,6 +74,16 @@ public:
   Context( Integration::GlAbstraction& glAbstraction );
 
   /**
+   * Creates the Dali Context object for texture (and surface rendering if required).
+   * This method does not create an OpenGL context i.e. that is done from outside dali-core.
+   * @pre Context has not been created.
+   * @exception Context already created.
+   * @param glAbstraction the gl abstraction.
+   * @param contexts The list of scene contexts (for surface rendering)
+   */
+  Context( Integration::GlAbstraction& glAbstraction, std::vector< Context* >* contexts );
+
+  /**
    * Destructor
    */
   ~Context();
@@ -99,7 +109,7 @@ public:
    */
   Integration::GlAbstraction& GetAbstraction() { return mGlAbstraction; }
 
-#ifdef DALI_CONTEXT_LOGGING
+#ifdef DEBUG_ENABLED
 
   /**
    * Debug helper which prints the currently cached GL state.
@@ -116,24 +126,31 @@ public:
   const char* ErrorToString( GLenum errorCode );
 
   /**
-   * Helper to check GL error during an operation
-   * @param operation that was performed
+   * Helper to print GL string to debug log
    */
-  void CheckGlError( const char* operation )
+  void PrintGlString(const char* stringName, GLenum stringId)
   {
-    for( GLint error = GetError(); error; error = GetError() )
-    {
-      DALI_LOG_ERROR( "glError (0x%x) %s - after %s\n",  error, ErrorToString(error), operation );
-      DALI_ASSERT_ALWAYS( error && "GL ERROR"); // if errors are being checked we should assert
-    }
+    DALI_LOG_INFO(Debug::Filter::gRender, Debug::General, "GL %s = %s\n", stringName, reinterpret_cast< const char * >( GetString( stringId ) ) );
   }
 
-  /**
-   * Helper to print GL string to debug log
-   */
-  void PrintGlString(const char* stringName, GLenum stringId)
+  void ResetBufferCache()
   {
-    DALI_LOG_INFO(Debug::Filter::gRender, Debug::General, "GL %s = %s\n", stringName, (const char *)GetString( stringId ) );
+    // reset the cached buffer id's
+    // fixes problem where some drivers will a generate a buffer with the
+    // same id, as the last deleted buffer id.
+    mBoundArrayBufferId = 0;
+    mBoundElementArrayBufferId = 0;
+    mBoundTransformFeedbackBufferId = 0;
+  }
+
+  void ResetTextureCache()
+  {
+    // reset the cached texture id's in case the driver re-uses them
+    // when creating new textures
+    for( unsigned int i=0; i < MAX_TEXTURE_UNITS; ++i )
+    {
+       mBoundTextureId[ i ] = 0;
+    }
   }
 
   /****************************************************************************************
@@ -144,18 +161,31 @@ public:
    ****************************************************************************************/
 
   /**
-   * Wrapper for OpenGL ES 2.0 glActiveTexture()
+   * Wrapper for IsSurfacelessContextSupported of Dali::Integration::GlAbstraction
    */
-  void ActiveTexture(GLenum textureUnit)
+  bool IsSurfacelessContextSupported() const
   {
-    // GL texture units are #defines in growing order to converting that to index
-    unsigned int unit = textureUnit - GL_TEXTURE0;
+    return mGlAbstraction.IsSurfacelessContextSupported();
+  }
 
-    if ( unit != mActiveTextureUnit )
+  /**
+   * Wrapper for TextureRequiresConverting of Dali::Integration::GlAbstraction
+   */
+  bool TextureRequiresConverting( const GLenum imageGlFormat, const GLenum textureGlFormat, const bool isSubImage ) const
+  {
+    return mGlAbstraction.TextureRequiresConverting( imageGlFormat, textureGlFormat, isSubImage );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glActiveTexture()
+   */
+  void ActiveTexture( TextureUnit textureUnit )
+  {
+    if ( textureUnit != mActiveTextureUnit )
     {
-      mActiveTextureUnit = unit;
+      mActiveTextureUnit = textureUnit;
       LOG_GL("ActiveTexture %x\n", textureUnit);
-      CHECK_GL( *this, mGlAbstraction.ActiveTexture(textureUnit) );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.ActiveTexture(TextureUnitAsGLenum(textureUnit)) );
     }
   }
 
@@ -165,7 +195,7 @@ public:
   void BeginQuery(GLenum target, GLuint id)
   {
     LOG_GL("BeginQuery %d %d\n", target, id);
-    CHECK_GL( *this, mGlAbstraction.BeginQuery(target, id) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BeginQuery(target, id) );
   }
 
   /**
@@ -174,7 +204,7 @@ public:
   void BeginTransformFeedback(GLenum primitiveMode)
   {
     LOG_GL("BeginTransformFeedback %x\n", primitiveMode);
-    CHECK_GL( *this, mGlAbstraction.BeginTransformFeedback(primitiveMode) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BeginTransformFeedback(primitiveMode) );
   }
 
   /**
@@ -192,7 +222,7 @@ public:
       mBoundArrayBufferId = buffer;
 
       LOG_GL("BindBuffer GL_ARRAY_BUFFER %d\n", buffer);
-      CHECK_GL( *this, mGlAbstraction.BindBuffer(GL_ARRAY_BUFFER, buffer) );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BindBuffer(GL_ARRAY_BUFFER, buffer) );
     }
   }
 
@@ -207,7 +237,7 @@ public:
       mBoundElementArrayBufferId = buffer;
 
       LOG_GL("BindBuffer GL_ELEMENT_ARRAY_BUFFER %d\n", buffer);
-      CHECK_GL( *this, mGlAbstraction.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer) );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer) );
     }
   }
 
@@ -222,7 +252,7 @@ public:
       mBoundTransformFeedbackBufferId = buffer;
 
       LOG_GL("BindBuffer GL_TRANSFORM_FEEDBACK_BUFFER %d\n", buffer);
-      CHECK_GL( *this, mGlAbstraction.BindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER , buffer) );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER , buffer) );
     }
   }
 
@@ -237,7 +267,7 @@ public:
       mBoundTransformFeedbackBufferId = buffer;
 
       LOG_GL("BindBufferBase GL_TRANSFORM_FEEDBACK_BUFFER %d %d\n", index, buffer);
-      CHECK_GL( *this, mGlAbstraction.BindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, index, buffer) );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, index, buffer) );
     }
   }
 
@@ -246,8 +276,10 @@ public:
    */
   void BindFramebuffer(GLenum target, GLuint framebuffer)
   {
+    mFrameBufferStateCache.SetCurrentFrameBuffer( framebuffer );
+
     LOG_GL("BindFramebuffer %d %d\n", target, framebuffer);
-    CHECK_GL( *this, mGlAbstraction.BindFramebuffer(target, framebuffer) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BindFramebuffer(target, framebuffer) );
   }
 
   /**
@@ -256,7 +288,7 @@ public:
   void BindRenderbuffer(GLenum target, GLuint renderbuffer)
   {
     LOG_GL("BindRenderbuffer %d %d\n", target, renderbuffer);
-    CHECK_GL( *this, mGlAbstraction.BindRenderbuffer(target, renderbuffer) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BindRenderbuffer(target, renderbuffer) );
   }
 
   /**
@@ -265,26 +297,38 @@ public:
   void BindTransformFeedback(GLenum target, GLuint id)
   {
     LOG_GL("BindTransformFeedback %d %d\n", target, id);
-    CHECK_GL( *this, mGlAbstraction.BindTransformFeedback(target, id) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BindTransformFeedback(target, id) );
   }
 
   /**
-   * The wrapper for OpenGL ES 2.0 glBindTexture() has been replaced by Bind2dTexture and BindCubeMapTexture.
+   * Helper to bind texture for rendering. If given texture is
+   * already bound in the given textureunit, this method does nothing.
+   * Otherwise changes the active texture unit and binds the texture.
+   * Note! after this call active texture unit may not necessarily be the one
+   * passed in as argument so you cannot change texture unit state!!
+   * @param textureunit to bind to
+   * @param texture to bind
    */
+  void BindTextureForUnit( TextureUnit textureunit, int target, GLuint texture )
+  {
+    if( mBoundTextureId[ textureunit ] != texture )
+    {
+      ActiveTexture( textureunit );
+      BindTexture( target, texture );
+    }
+  }
 
   /**
-   * Wrapper for OpenGL ES 2.0 glBindTexture(GL_TEXTURE_2D)
+   * Wrapper for OpenGL ES 2.0 glBindTexture( target )
    */
-  void Bind2dTexture( GLuint texture )
+  void BindTexture( int target, GLuint texture )
   {
-    if (mBound2dTextureId[ mActiveTextureUnit ] != texture)
+    if (mBoundTextureId[ mActiveTextureUnit ] != texture)
     {
-      mBound2dTextureId[ mActiveTextureUnit ] = texture;
+      mBoundTextureId[ mActiveTextureUnit ] = texture;
 
-      LOG_GL("BindTexture GL_TEXTURE_2D %d\n", texture);
-      CHECK_GL( *this, mGlAbstraction.BindTexture(GL_TEXTURE_2D, texture) );
-
-      INCREASE_COUNTER(PerformanceMonitor::TEXTURE_STATE_CHANGES);
+      LOG_GL("BindTexture target(%d) %d\n", target, texture);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BindTexture(target, texture) );
     }
   }
 
@@ -293,10 +337,9 @@ public:
    */
   void SetDefaultBlendColor()
   {
-    if( !mUsingDefaultBlendColor )
+    if( ! mUsingDefaultBlendColor )
     {
-      LOG_GL( "BlendColor %f %f %f %f\n", 0.0f, 0.0f, 0.0f, 0.0f );
-      CHECK_GL( *this, mGlAbstraction.BlendColor( 0.0f, 0.0f, 0.0f, 0.0f ) );
+      SetCustomBlendColor( Color::TRANSPARENT );
       mUsingDefaultBlendColor = true;
     }
   }
@@ -306,9 +349,13 @@ public:
    */
   void SetCustomBlendColor( const Vector4& color )
   {
-    LOG_GL( "BlendColor %f %f %f %f\n", color.r, color.g, color.b, color.a );
-    CHECK_GL( *this, mGlAbstraction.BlendColor(color.r, color.g, color.b, color.a) );
-    mUsingDefaultBlendColor = false;
+    if( mUsingDefaultBlendColor || mBlendColor != color )
+    {
+      LOG_GL( "BlendColor %f %f %f %f\n", color.r, color.g, color.b, color.a );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BlendColor( color.r, color.g, color.b, color.a ) );
+      mUsingDefaultBlendColor = false;
+      mBlendColor = color;
+    }
   }
 
   /**
@@ -331,7 +378,7 @@ public:
       mBlendEquationSeparateModeRGB = modeRGB;
       mBlendEquationSeparateModeAlpha = modeAlpha;
       LOG_GL("BlendEquationSeparate %d %d\n", modeRGB, modeAlpha);
-      CHECK_GL( *this, mGlAbstraction.BlendEquationSeparate(modeRGB, modeAlpha) );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BlendEquationSeparate(modeRGB, modeAlpha) );
     }
   }
 
@@ -358,7 +405,7 @@ public:
       mBlendFuncSeparateDstAlpha = dstAlpha;
 
       LOG_GL( "BlendFuncSeparate %d %d %d %d\n", srcRGB, dstRGB, srcAlpha, dstAlpha );
-      CHECK_GL( *this, mGlAbstraction.BlendFuncSeparate( srcRGB, dstRGB, srcAlpha, dstAlpha ) );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BlendFuncSeparate( srcRGB, dstRGB, srcAlpha, dstAlpha ) );
     }
   }
 
@@ -368,7 +415,7 @@ public:
   void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
   {
     LOG_GL( "BlitFramebuffer %d %d %d %d %d %d %d %d %x %d\n", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter );
-    CHECK_GL( *this, mGlAbstraction.BlitFramebuffer( srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter ) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BlitFramebuffer( srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter ) );
   }
 
   /**
@@ -377,7 +424,7 @@ public:
   void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage)
   {
     LOG_GL("BufferData %d %d %p %d\n", target, size, data, usage);
-    CHECK_GL( *this, mGlAbstraction.BufferData(target, size, data, usage) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BufferData(target, size, data, usage) );
   }
 
   /**
@@ -386,7 +433,7 @@ public:
   void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void* data)
   {
     LOG_GL("BufferSubData %d %d %d %p\n", target, offset, size, data);
-    CHECK_GL( *this, mGlAbstraction.BufferSubData(target, offset, size, data) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BufferSubData(target, offset, size, data) );
   }
 
   /**
@@ -395,17 +442,23 @@ public:
   GLenum CheckFramebufferStatus(GLenum target)
   {
     LOG_GL("CheckFramebufferStatus %d\n", target);
-    GLenum value = CHECK_GL( *this, mGlAbstraction.CheckFramebufferStatus(target) );
+    GLenum value = CHECK_GL( mGlAbstraction, mGlAbstraction.CheckFramebufferStatus(target) );
     return value;
   }
 
   /**
    * Wrapper for OpenGL ES 2.0 glClear()
    */
-  void Clear(GLbitfield mask)
+  void Clear(GLbitfield mask, ClearMode mode )
   {
-    LOG_GL("Clear %d\n", mask);
-    CHECK_GL( *this, mGlAbstraction.Clear(mask) );
+    bool forceClear = (mode == FORCE_CLEAR );
+    mask = mFrameBufferStateCache.GetClearMask( mask, forceClear , mScissorTestEnabled );
+
+    if( mask > 0 )
+    {
+      LOG_GL("Clear %d\n", mask);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.Clear( mask ) );
+    }
   }
 
   /**
@@ -418,7 +471,7 @@ public:
     if (!mClearColorSet || mClearColor !=newCol )
     {
       LOG_GL("ClearColor %f %f %f %f\n", red, green, blue, alpha);
-      CHECK_GL( *this, mGlAbstraction.ClearColor(red, green, blue, alpha) );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.ClearColor(red, green, blue, alpha) );
 
       mClearColorSet = true;
       mClearColor = newCol;
@@ -431,7 +484,7 @@ public:
   void ClearDepthf(GLclampf depth)
   {
     LOG_GL("ClearDepthf %f\n", depth);
-    CHECK_GL( *this, mGlAbstraction.ClearDepthf(depth) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.ClearDepthf(depth) );
   }
 
   /**
@@ -440,7 +493,7 @@ public:
   void ClearStencil(GLint s)
   {
     LOG_GL("ClearStencil %d\n", s);
-    CHECK_GL( *this, mGlAbstraction.ClearStencil(s) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.ClearStencil(s) );
   }
 
   /**
@@ -454,7 +507,7 @@ public:
     {
       mColorMask = flag;
       LOG_GL("ColorMask %s %s %s %s\n", flag ? "True" : "False", flag ? "True" : "False", flag ? "True" : "False", flag ? "True" : "False");
-      CHECK_GL( *this, mGlAbstraction.ColorMask(flag, flag, flag, flag) );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.ColorMask(flag, flag, flag, flag) );
     }
   }
 
@@ -465,7 +518,7 @@ public:
                             GLint border, GLsizei imageSize, const void* data)
   {
     LOG_GL("CompressedTexImage2D %d %d %x %d %d %d %d %p\n", target, level, internalformat, width, height, border, imageSize, data);
-    CHECK_GL( *this, mGlAbstraction.CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data) );
   }
 
   /**
@@ -475,7 +528,7 @@ public:
                             GLint border, GLsizei imageSize, const void* data)
   {
     LOG_GL("CompressedTexImage3D %d %d %x %d %d %d %d %d %p\n", target, level, internalformat, width, height, depth, border, imageSize, data);
-    CHECK_GL( *this, mGlAbstraction.CompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data) );
   }
 
   /**
@@ -485,7 +538,7 @@ public:
                                GLenum format, GLsizei imageSize, const void* data)
   {
     LOG_GL("CompressedTexSubImage2D %x %d %d %d %d %d %x %d %p\n", target, level, xoffset, yoffset, width, height, format, imageSize, data);
-    CHECK_GL( *this, mGlAbstraction.CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data) );
   }
 
   /**
@@ -496,7 +549,7 @@ public:
                                GLenum format, GLsizei imageSize, const void* data)
   {
     LOG_GL("CompressedTexSubImage3D %x %d %d %d %d %d %d %d %x %d %p\n", target, level, xoffset, yoffset, xoffset, width, height, depth, format, imageSize, data);
-    CHECK_GL( *this, mGlAbstraction.CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data) );
   }
 
   /**
@@ -505,7 +558,7 @@ public:
   void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
   {
     LOG_GL("CopyTexImage2D %x %d %x %d %d %d %d %d\n", target, level, internalformat, x, y, width, height, border);
-    CHECK_GL( *this, mGlAbstraction.CopyTexImage2D(target, level, internalformat, x, y, width, height, border) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CopyTexImage2D(target, level, internalformat, x, y, width, height, border) );
   }
 
   /**
@@ -514,7 +567,7 @@ public:
   void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
   {
     LOG_GL("CopyTexSubImage2D %x %d %d %d %d %d %d %d\n", target, level, xoffset, yoffset, x, y, width, height);
-    CHECK_GL( *this, mGlAbstraction.CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height) );
   }
 
   /**
@@ -523,7 +576,7 @@ public:
   void CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
   {
     LOG_GL("CopyTexSubImage3D %x %d %d %d %d %d %d %d %d\n", target, level, xoffset, yoffset, zoffset, x, y, width, height);
-    CHECK_GL( *this, mGlAbstraction.CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height) );
   }
 
   /**
@@ -531,7 +584,7 @@ public:
    * enables GL_CULL_FACE if in any of the face culling modes
    * otherwise disables GL_CULL_FACE
    */
-  void CullFace(CullFaceMode mode)
+  void CullFace( Dali::FaceCullingMode::Type mode )
   {
     // Avoid unnecessary calls to gl
     if(mCullFaceMode != mode)
@@ -539,37 +592,37 @@ public:
       mCullFaceMode = mode;
       switch(mode)
       {
-        case CullNone:
+        case Dali::FaceCullingMode::NONE:
         {
           LOG_GL("Disable GL_CULL_FACE\n");
-          CHECK_GL( *this, mGlAbstraction.Disable(GL_CULL_FACE) );
+          CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_CULL_FACE) );
           break;
         }
 
-        case CullFront:
+        case Dali::FaceCullingMode::FRONT:
         {
           LOG_GL("Enable GL_CULL_FACE\n");
-          CHECK_GL( *this, mGlAbstraction.Enable(GL_CULL_FACE) );
+          CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_CULL_FACE) );
           LOG_GL("Enable GL_FRONT\n");
-          CHECK_GL( *this, mGlAbstraction.CullFace(GL_FRONT) );
+          CHECK_GL( mGlAbstraction, mGlAbstraction.CullFace(GL_FRONT) );
           break;
         }
 
-        case CullBack:
+        case Dali::FaceCullingMode::BACK:
         {
           LOG_GL("Enable GL_CULL_FACE\n");
-          CHECK_GL( *this, mGlAbstraction.Enable(GL_CULL_FACE) );
+          CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_CULL_FACE) );
           LOG_GL("Enable GL_BACK\n");
-          CHECK_GL( *this, mGlAbstraction.CullFace(GL_BACK) );
+          CHECK_GL( mGlAbstraction, mGlAbstraction.CullFace(GL_BACK) );
           break;
         }
 
-        case CullFrontAndBack:
+        case Dali::FaceCullingMode::FRONT_AND_BACK:
         {
           LOG_GL("Enable GL_CULL_FACE\n");
-          CHECK_GL( *this, mGlAbstraction.Enable(GL_CULL_FACE) );
+          CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_CULL_FACE) );
           LOG_GL("Enable GL_FRONT_AND_BACK\n");
-          CHECK_GL( *this, mGlAbstraction.CullFace(GL_FRONT_AND_BACK) );
+          CHECK_GL( mGlAbstraction, mGlAbstraction.CullFace(GL_FRONT_AND_BACK) );
           break;
         }
 
@@ -584,19 +637,26 @@ public:
    */
   void DeleteBuffers(GLsizei n, const GLuint* buffers)
   {
-    // @todo: this is to prevent mesh destructor from doing GL calls when DALi core is being deleted
-    // can be taken out once render manages either knows about meshes or gpubuffers and can tell them directly that context is lost
     if( this->IsGlContextCreated() )
     {
       LOG_GL("DeleteBuffers %d %p\n", n, buffers);
-      CHECK_GL( *this, mGlAbstraction.DeleteBuffers(n, buffers) );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteBuffers(n, buffers) );
+    }
+
+    ResetBufferCache();
+
+    // Need to reset the buffer cache in the surface contexts
+    // This will only be executed by the surfaceless context when there are contexts for surface rendering
+    if ( mSceneContexts )
+    {
+      for ( auto&& context : *mSceneContexts )
+      {
+        if ( context )
+        {
+          context->ResetBufferCache();
+        }
+      }
     }
-    // reset the cached buffer id's
-    // fixes problem where some drivers will a generate a buffer with the
-    // same id, as the last deleted buffer id.
-    mBoundArrayBufferId = 0;
-    mBoundElementArrayBufferId = 0;
-    mBoundTransformFeedbackBufferId = 0;
   }
 
   /**
@@ -604,8 +664,10 @@ public:
    */
   void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
   {
+    mFrameBufferStateCache.FrameBuffersDeleted( n, framebuffers );
+
     LOG_GL("DeleteFramebuffers %d %p\n", n, framebuffers);
-    CHECK_GL( *this, mGlAbstraction.DeleteFramebuffers(n, framebuffers) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteFramebuffers(n, framebuffers) );
   }
 
   /**
@@ -614,7 +676,7 @@ public:
   void DeleteQueries(GLsizei n, GLuint* ids)
   {
     LOG_GL("DeleteQueries %d %p\n", n, ids);
-    CHECK_GL( *this, mGlAbstraction.DeleteQueries(n, ids) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteQueries(n, ids) );
   }
 
   /**
@@ -623,7 +685,7 @@ public:
   void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
   {
     LOG_GL("DeleteRenderbuffers %d %p\n", n, renderbuffers);
-    CHECK_GL( *this, mGlAbstraction.DeleteRenderbuffers(n, renderbuffers) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteRenderbuffers(n, renderbuffers) );
   }
 
   /**
@@ -632,13 +694,21 @@ public:
   void DeleteTextures(GLsizei n, const GLuint* textures)
   {
     LOG_GL("DeleteTextures %d %p\n", n, textures);
-    CHECK_GL( *this, mGlAbstraction.DeleteTextures(n, textures) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteTextures(n, textures) );
 
-    // reset the cached texture id's incase the driver re-uses them
-    // when creating new textures
-    for( int i=0; i < mMaxTextureUnits; ++i )
+    ResetTextureCache();
+
+    // Need to reset the texture cache in the scene contexts
+    // This will only be executed by the surfaceless context when there are contexts for surface rendering
+    if ( mSceneContexts )
     {
-       mBound2dTextureId[ i ] = 0;
+      for ( auto&& context : *mSceneContexts )
+      {
+        if ( context )
+        {
+          context->ResetTextureCache();
+        }
+      }
     }
   }
 
@@ -648,7 +718,7 @@ public:
   void DeleteTransformFeedbacks(GLsizei n, GLuint* ids)
   {
     LOG_GL("DeleteTransformFeedbacks %d %p\n", n, ids);
-    CHECK_GL( *this, mGlAbstraction.DeleteTransformFeedbacks(n, ids) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteTransformFeedbacks(n, ids) );
   }
 
   /**
@@ -656,8 +726,12 @@ public:
    */
   void DepthFunc(GLenum func)
   {
-    LOG_GL("DepthFunc %x\n", func);
-    CHECK_GL( *this, mGlAbstraction.DepthFunc(func) );
+    if( func != mDepthFunction )
+    {
+      mDepthFunction = func;
+      LOG_GL("DepthFunc %x\n", func);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.DepthFunc(func) );
+    }
   }
 
   /**
@@ -665,12 +739,13 @@ public:
    */
   void DepthMask(GLboolean flag)
   {
+    bool booleanFlag = flag != GL_FALSE;
     // only change state if needed
-    if( flag != mDepthMaskEnabled )
+    if( booleanFlag != mDepthMaskEnabled )
     {
-      mDepthMaskEnabled = flag;
-      LOG_GL("DepthMask %s\n", flag ? "True" : "False");
-      CHECK_GL( *this, mGlAbstraction.DepthMask( mDepthMaskEnabled ) );
+      mDepthMaskEnabled = booleanFlag;
+      LOG_GL("DepthMask %s\n", booleanFlag ? "True" : "False");
+      CHECK_GL( mGlAbstraction, mGlAbstraction.DepthMask( mDepthMaskEnabled ) );
     }
   }
 
@@ -680,7 +755,7 @@ public:
   void DepthRangef(GLclampf zNear, GLclampf zFar)
   {
     LOG_GL("DepthRangef %f %f\n", zNear, zFar);
-    CHECK_GL( *this, mGlAbstraction.DepthRangef(zNear, zFar) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DepthRangef(zNear, zFar) );
   }
 
   /**
@@ -693,10 +768,11 @@ public:
    */
   void DrawArrays(GLenum mode, GLint first, GLsizei count)
   {
+    mFrameBufferStateCache.DrawOperation( mColorMask, DepthBufferWriteEnabled(), StencilBufferWriteEnabled() );
     FlushVertexAttributeLocations();
 
     LOG_GL("DrawArrays %x %d %d\n", mode, first, count);
-    CHECK_GL( *this, mGlAbstraction.DrawArrays(mode, first, count) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DrawArrays(mode, first, count) );
   }
 
   /**
@@ -704,10 +780,11 @@ public:
    */
   void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
   {
+    mFrameBufferStateCache.DrawOperation( mColorMask, DepthBufferWriteEnabled(), StencilBufferWriteEnabled() );
     FlushVertexAttributeLocations();
 
     LOG_GL("DrawArraysInstanced %x %d %d %d\n", mode, first, count, instanceCount);
-    CHECK_GL( *this, mGlAbstraction.DrawArraysInstanced(mode, first, count,instanceCount) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DrawArraysInstanced(mode, first, count,instanceCount) );
   }
 
   /**
@@ -715,8 +792,9 @@ public:
    */
   void DrawBuffers(GLsizei n, const GLenum* bufs)
   {
+    mFrameBufferStateCache.DrawOperation( mColorMask, DepthBufferWriteEnabled(), StencilBufferWriteEnabled() );
     LOG_GL("DrawBuffers %d %p\n", n, bufs);
-    CHECK_GL( *this, mGlAbstraction.DrawBuffers(n, bufs) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DrawBuffers(n, bufs) );
   }
 
   /**
@@ -724,10 +802,12 @@ public:
    */
   void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
   {
+    mFrameBufferStateCache.DrawOperation( mColorMask, DepthBufferWriteEnabled(), StencilBufferWriteEnabled() );
+
     FlushVertexAttributeLocations();
 
     LOG_GL("DrawElements %x %d %d %p\n", mode, count, type, indices);
-    CHECK_GL( *this, mGlAbstraction.DrawElements(mode, count, type, indices) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DrawElements(mode, count, type, indices) );
   }
 
   /**
@@ -735,10 +815,12 @@ public:
    */
   void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instanceCount)
   {
+    mFrameBufferStateCache.DrawOperation( mColorMask, DepthBufferWriteEnabled(), StencilBufferWriteEnabled() );
+
     FlushVertexAttributeLocations();
 
     LOG_GL("DrawElementsInstanced %x %d %d %p %d\n", mode, count, type, indices, instanceCount);
-    CHECK_GL( *this, mGlAbstraction.DrawElementsInstanced(mode, count, type, indices, instanceCount) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DrawElementsInstanced(mode, count, type, indices, instanceCount) );
   }
 
   /**
@@ -746,10 +828,11 @@ public:
    */
   void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
   {
+    mFrameBufferStateCache.DrawOperation( mColorMask, DepthBufferWriteEnabled(), StencilBufferWriteEnabled() );
     FlushVertexAttributeLocations();
 
     LOG_GL("DrawRangeElements %x %u %u %d %d %p\n", mode, start, end, count, type, indices);
-    CHECK_GL( *this, mGlAbstraction.DrawRangeElements(mode, start, end, count, type, indices) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DrawRangeElements(mode, start, end, count, type, indices) );
   }
 
   /**
@@ -758,7 +841,7 @@ public:
   void GenQueries(GLsizei n, GLuint* ids)
   {
     LOG_GL("GenQueries %d %p\n", n, ids);
-    CHECK_GL( *this, mGlAbstraction.GenQueries(n, ids) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenQueries(n, ids) );
   }
 
   /**
@@ -767,7 +850,7 @@ public:
   void GenTransformFeedbacks(GLsizei n, GLuint* ids)
   {
     LOG_GL("GenTransformFeedbacks %d %p\n", n, ids);
-    CHECK_GL( *this, mGlAbstraction.GenTransformFeedbacks(n, ids) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenTransformFeedbacks(n, ids) );
   }
 
   /**
@@ -816,8 +899,8 @@ public:
    */
   void VertexAttribDivisor ( GLuint index, GLuint divisor )
   {
-    LOG_GL("VertexAttribPointer(%d, %d)\n", index, divisor );
-    CHECK_GL( *this, mGlAbstraction.VertexAttribDivisor( index, divisor ) );
+    LOG_GL("VertexAttribDivisor(%d, %d)\n", index, divisor );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.VertexAttribDivisor( index, divisor ) );
   }
 
   /**
@@ -826,7 +909,7 @@ public:
   void VertexAttribPointer( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr )
   {
     LOG_GL("VertexAttribPointer(%d, %d, %d, %d, %d, %x)\n", index, size, type, normalized, stride, ptr );
-    CHECK_GL( *this, mGlAbstraction.VertexAttribPointer( index, size, type, normalized, stride, ptr ) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.VertexAttribPointer( index, size, type, normalized, stride, ptr ) );
   }
 
   /**
@@ -835,7 +918,7 @@ public:
   void InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)
   {
     LOG_GL("InvalidateFramebuffer\n");
-    CHECK_GL( *this, mGlAbstraction.InvalidateFramebuffer(target, numAttachments, attachments) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.InvalidateFramebuffer(target, numAttachments, attachments) );
   }
 
   /**
@@ -857,36 +940,40 @@ public:
       if (enable)
       {
         LOG_GL("Enable GL_BLEND\n");
-        CHECK_GL( *this, mGlAbstraction.Enable(GL_BLEND) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_BLEND) );
       }
       else
       {
         LOG_GL("Disable GL_BLEND\n");
-        CHECK_GL( *this, mGlAbstraction.Disable(GL_BLEND) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_BLEND) );
       }
     }
   }
 
   /**
    * This method replaces glEnable(GL_DEPTH_TEST) and glDisable(GL_DEPTH_TEST).
+   * Note GL_DEPTH_TEST means enable the depth buffer for writing and or testing.
+   * glDepthMask is used to enable / disable writing to depth buffer.
+   * glDepthFunc us used to control if testing is enabled and how it is performed ( default GL_LESS)
+   *
    * @param[in] enable True if GL_DEPTH_TEST should be enabled.
    */
-  void SetDepthTest(bool enable)
+  void EnableDepthBuffer( bool enable )
   {
     // Avoid unecessary calls to glEnable/glDisable
-    if (enable != mDepthTestEnabled)
+    if( enable != mDepthBufferEnabled )
     {
-      mDepthTestEnabled = enable;
+      mDepthBufferEnabled = enable;
 
       if (enable)
       {
         LOG_GL("Enable GL_DEPTH_TEST\n");
-        CHECK_GL( *this, mGlAbstraction.Enable(GL_DEPTH_TEST) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_DEPTH_TEST) );
       }
       else
       {
         LOG_GL("Disable GL_DEPTH_TEST\n");
-        CHECK_GL( *this, mGlAbstraction.Disable(GL_DEPTH_TEST) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_DEPTH_TEST) );
       }
     }
   }
@@ -905,12 +992,12 @@ public:
       if (enable)
       {
         LOG_GL("Enable GL_DITHER\n");
-        CHECK_GL( *this, mGlAbstraction.Enable(GL_DITHER) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_DITHER) );
       }
       else
       {
         LOG_GL("Disable GL_DITHER\n");
-        CHECK_GL( *this, mGlAbstraction.Disable(GL_DITHER) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_DITHER) );
       }
     }
   }
@@ -929,12 +1016,12 @@ public:
       if (enable)
       {
         LOG_GL("Enable GL_POLYGON_OFFSET_FILL\n");
-        CHECK_GL( *this, mGlAbstraction.Enable(GL_POLYGON_OFFSET_FILL) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_POLYGON_OFFSET_FILL) );
       }
       else
       {
         LOG_GL("Disable GL_POLYGON_OFFSET_FILL\n");
-        CHECK_GL( *this, mGlAbstraction.Disable(GL_POLYGON_OFFSET_FILL) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_POLYGON_OFFSET_FILL) );
       }
     }
   }
@@ -953,12 +1040,12 @@ public:
       if (enable)
       {
         LOG_GL("Enable GL_SAMPLE_ALPHA_TO_COVERAGE\n");
-        CHECK_GL( *this, mGlAbstraction.Enable(GL_SAMPLE_ALPHA_TO_COVERAGE) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_SAMPLE_ALPHA_TO_COVERAGE) );
       }
       else
       {
         LOG_GL("Disable GL_SAMPLE_ALPHA_TO_COVERAGE\n");
-        CHECK_GL( *this, mGlAbstraction.Disable(GL_SAMPLE_ALPHA_TO_COVERAGE) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_SAMPLE_ALPHA_TO_COVERAGE) );
       }
     }
   }
@@ -977,12 +1064,12 @@ public:
       if (enable)
       {
         LOG_GL("Enable GL_SAMPLE_COVERAGE\n");
-        CHECK_GL( *this, mGlAbstraction.Enable(GL_SAMPLE_COVERAGE) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_SAMPLE_COVERAGE) );
       }
       else
       {
         LOG_GL("Disable GL_SAMPLE_COVERAGE\n");
-        CHECK_GL( *this, mGlAbstraction.Disable(GL_SAMPLE_COVERAGE) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_SAMPLE_COVERAGE) );
       }
     }
   }
@@ -1001,36 +1088,39 @@ public:
       if (enable)
       {
         LOG_GL("Enable GL_SCISSOR_TEST\n");
-        CHECK_GL( *this, mGlAbstraction.Enable(GL_SCISSOR_TEST) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_SCISSOR_TEST) );
       }
       else
       {
         LOG_GL("Disable GL_SCISSOR_TEST\n");
-        CHECK_GL( *this, mGlAbstraction.Disable(GL_SCISSOR_TEST) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_SCISSOR_TEST) );
       }
     }
   }
 
   /**
    * This method replaces glEnable(GL_STENCIL_TEST) and glDisable(GL_STENCIL_TEST).
+   * Note GL_STENCIL_TEST means enable the stencil buffer for writing and or testing.
+   * glStencilMask is used to control how bits are written to the stencil buffer.
+   * glStencilFunc is used to control if testing is enabled and how it is performed ( default GL_ALWAYS )
    * @param[in] enable True if GL_STENCIL_TEST should be enabled.
    */
-  void SetStencilTest(bool enable)
+  void EnableStencilBuffer(bool enable)
   {
     // Avoid unecessary calls to glEnable/glDisable
-    if (enable != mStencilTestEnabled)
+    if( enable != mStencilBufferEnabled )
     {
-      mStencilTestEnabled = enable;
+      mStencilBufferEnabled = enable;
 
       if (enable)
       {
         LOG_GL("Enable GL_STENCIL_TEST\n");
-        CHECK_GL( *this, mGlAbstraction.Enable(GL_STENCIL_TEST) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_STENCIL_TEST) );
       }
       else
       {
         LOG_GL("Disable GL_STENCIL_TEST\n");
-        CHECK_GL( *this, mGlAbstraction.Disable(GL_STENCIL_TEST) );
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_STENCIL_TEST) );
       }
     }
   }
@@ -1041,7 +1131,7 @@ public:
   void EndQuery(GLenum target)
   {
     LOG_GL("EndQuery %d\n", target);
-    CHECK_GL( *this, mGlAbstraction.EndQuery(target) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.EndQuery(target) );
   }
 
   /**
@@ -1050,7 +1140,7 @@ public:
   void EndTransformFeedback()
   {
     LOG_GL("EndTransformFeedback\n");
-    CHECK_GL( *this, mGlAbstraction.EndTransformFeedback() );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.EndTransformFeedback() );
   }
 
   /**
@@ -1059,7 +1149,7 @@ public:
   void Finish(void)
   {
     LOG_GL("Finish\n");
-    CHECK_GL( *this, mGlAbstraction.Finish() );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.Finish() );
   }
 
   /**
@@ -1068,7 +1158,7 @@ public:
   void Flush(void)
   {
     LOG_GL("Flush\n");
-    CHECK_GL( *this, mGlAbstraction.Flush() );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.Flush() );
   }
 
   /**
@@ -1077,7 +1167,7 @@ public:
   void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
   {
     LOG_GL("FramebufferRenderbuffer %x %x %x %d\n", target, attachment, renderbuffertarget, renderbuffer);
-    CHECK_GL( *this, mGlAbstraction.FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer) );
   }
 
   /**
@@ -1086,7 +1176,7 @@ public:
   void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
   {
     LOG_GL("FramebufferTexture2D %x %x %x %d %d\n", target, attachment, textarget, texture, level);
-    CHECK_GL( *this, mGlAbstraction.FramebufferTexture2D(target, attachment, textarget, texture, level) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.FramebufferTexture2D(target, attachment, textarget, texture, level) );
   }
 
   /**
@@ -1095,7 +1185,7 @@ public:
   void FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
   {
     LOG_GL("FramebufferTextureLayer %x %x %d %d %d\n", target, attachment, texture, level, layer);
-    CHECK_GL( *this, mGlAbstraction.FramebufferTextureLayer(target, attachment, texture, level, layer) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.FramebufferTextureLayer(target, attachment, texture, level, layer) );
   }
 
   /**
@@ -1104,7 +1194,7 @@ public:
   void FrontFace(GLenum mode)
   {
     LOG_GL("FrontFace %x\n", mode);
-    CHECK_GL( *this, mGlAbstraction.FrontFace(mode) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.FrontFace(mode) );
   }
 
   /**
@@ -1113,7 +1203,7 @@ public:
   void GenBuffers(GLsizei n, GLuint* buffers)
   {
     LOG_GL("GenBuffers %d\n", n, buffers);
-    CHECK_GL( *this, mGlAbstraction.GenBuffers(n, buffers) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenBuffers(n, buffers) );
   }
 
   /**
@@ -1122,7 +1212,7 @@ public:
   void GenerateMipmap(GLenum target)
   {
     LOG_GL("GenerateMipmap %x\n", target);
-    CHECK_GL( *this, mGlAbstraction.GenerateMipmap(target) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenerateMipmap(target) );
   }
 
   /**
@@ -1131,7 +1221,9 @@ public:
   void GenFramebuffers(GLsizei n, GLuint* framebuffers)
   {
     LOG_GL("GenFramebuffers %d %p\n", n, framebuffers);
-    CHECK_GL( *this, mGlAbstraction.GenFramebuffers(n, framebuffers) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenFramebuffers(n, framebuffers) );
+
+    mFrameBufferStateCache.FrameBuffersCreated( n, framebuffers );
   }
 
   /**
@@ -1140,7 +1232,7 @@ public:
   void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
   {
     LOG_GL("GenRenderbuffers %d %p\n", n, renderbuffers);
-    CHECK_GL( *this, mGlAbstraction.GenRenderbuffers(n, renderbuffers) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenRenderbuffers(n, renderbuffers) );
   }
 
   /**
@@ -1149,7 +1241,7 @@ public:
   void GenTextures(GLsizei n, GLuint* textures)
   {
     LOG_GL("GenTextures %d %p\n", n, textures);
-    CHECK_GL( *this, mGlAbstraction.GenTextures(n, textures) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenTextures(n, textures) );
   }
 
   /**
@@ -1158,7 +1250,7 @@ public:
   void GetBooleanv(GLenum pname, GLboolean* params)
   {
     LOG_GL("GetBooleanv %x\n", pname);
-    CHECK_GL( *this, mGlAbstraction.GetBooleanv(pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetBooleanv(pname, params) );
   }
 
   /**
@@ -1167,7 +1259,7 @@ public:
   void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
   {
     LOG_GL("GetBufferParameteriv %x %x %p\n", target, pname, params);
-    CHECK_GL( *this, mGlAbstraction.GetBufferParameteriv(target, pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetBufferParameteriv(target, pname, params) );
   }
 
   /**
@@ -1176,7 +1268,7 @@ public:
   void GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
   {
     LOG_GL("GetBufferPointerv %x %x %p\n", target, pname, params);
-    CHECK_GL( *this, mGlAbstraction.GetBufferPointerv(target, pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetBufferPointerv(target, pname, params) );
   }
 
   /**
@@ -1194,7 +1286,7 @@ public:
   void GetFloatv(GLenum pname, GLfloat* params)
   {
     LOG_GL("GetFloatv %x\n", pname);
-    CHECK_GL( *this, mGlAbstraction.GetFloatv(pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetFloatv(pname, params) );
   }
 
   /**
@@ -1203,7 +1295,7 @@ public:
   void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
   {
     LOG_GL("GetFramebufferAttachmentParameteriv %x %x %x\n", target, attachment, pname);
-    CHECK_GL( *this, mGlAbstraction.GetFramebufferAttachmentParameteriv(target, attachment, pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetFramebufferAttachmentParameteriv(target, attachment, pname, params) );
   }
 
   /**
@@ -1212,7 +1304,7 @@ public:
   void GetIntegerv(GLenum pname, GLint* params)
   {
     LOG_GL("GetIntegerv %x\n", pname);
-    CHECK_GL( *this, mGlAbstraction.GetIntegerv(pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetIntegerv(pname, params) );
   }
 
   /**
@@ -1221,7 +1313,7 @@ public:
   void GetQueryiv(GLenum target, GLenum pname, GLint* params)
   {
     LOG_GL("GetQueryiv %x %x\n", target, pname);
-    CHECK_GL( *this, mGlAbstraction.GetQueryiv(target, pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetQueryiv(target, pname, params) );
   }
 
   /**
@@ -1230,7 +1322,7 @@ public:
   void GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
   {
     LOG_GL("GetQueryObjectuiv %u %x %p\n", id, pname, params);
-    CHECK_GL( *this, mGlAbstraction.GetQueryObjectuiv(id, pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetQueryObjectuiv(id, pname, params) );
   }
 
   /**
@@ -1239,7 +1331,7 @@ public:
   void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
   {
     LOG_GL("GetRenderbufferParameteriv %x %x\n", target, pname);
-    CHECK_GL( *this, mGlAbstraction.GetRenderbufferParameteriv(target, pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetRenderbufferParameteriv(target, pname, params) );
   }
 
   /**
@@ -1248,7 +1340,7 @@ public:
   const GLubyte* GetString(GLenum name)
   {
     LOG_GL("GetString %x\n", name);
-    const GLubyte* str = CHECK_GL( *this, mGlAbstraction.GetString(name) );
+    const GLubyte* str = CHECK_GL( mGlAbstraction, mGlAbstraction.GetString(name) );
     return str;
   }
 
@@ -1258,7 +1350,7 @@ public:
   void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
   {
     LOG_GL("GetTexParameterfv %x %x\n", target, pname);
-    CHECK_GL( *this, mGlAbstraction.GetTexParameterfv(target, pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetTexParameterfv(target, pname, params) );
   }
 
   /**
@@ -1267,7 +1359,7 @@ public:
   void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
   {
     LOG_GL("GetTexParameteriv %x %x\n", target, pname);
-    CHECK_GL( *this, mGlAbstraction.GetTexParameteriv(target, pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetTexParameteriv(target, pname, params) );
   }
 
   /**
@@ -1276,7 +1368,7 @@ public:
   void Hint(GLenum target, GLenum mode)
   {
     LOG_GL("Hint %x %x\n", target, mode);
-    CHECK_GL( *this, mGlAbstraction.Hint(target, mode) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.Hint(target, mode) );
   }
 
   /**
@@ -1285,7 +1377,7 @@ public:
   GLboolean IsBuffer(GLuint buffer)
   {
     LOG_GL("IsBuffer %d\n", buffer);
-    GLboolean val = CHECK_GL( *this, mGlAbstraction.IsBuffer(buffer) );
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsBuffer(buffer) );
     return val;
   }
 
@@ -1295,7 +1387,7 @@ public:
   GLboolean IsEnabled(GLenum cap)
   {
     LOG_GL("IsEnabled %x\n", cap);
-    GLboolean val = CHECK_GL( *this, mGlAbstraction.IsEnabled(cap) );
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsEnabled(cap) );
     return val;
   }
 
@@ -1305,7 +1397,7 @@ public:
   GLboolean IsFramebuffer(GLuint framebuffer)
   {
     LOG_GL("IsFramebuffer %d\n", framebuffer);
-    GLboolean val = CHECK_GL( *this, mGlAbstraction.IsFramebuffer(framebuffer) );
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsFramebuffer(framebuffer) );
     return val;
   }
 
@@ -1315,7 +1407,7 @@ public:
   GLboolean IsQuery(GLuint id)
   {
     LOG_GL("IsQuery %u\n", id);
-    GLboolean val = CHECK_GL( *this, mGlAbstraction.IsQuery(id) );
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsQuery(id) );
     return val;
   }
 
@@ -1325,7 +1417,7 @@ public:
   GLboolean IsRenderbuffer(GLuint renderbuffer)
   {
     LOG_GL("IsRenderbuffer %d\n", renderbuffer);
-    GLboolean val = CHECK_GL( *this, mGlAbstraction.IsRenderbuffer(renderbuffer) );
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsRenderbuffer(renderbuffer) );
     return val;
   }
 
@@ -1335,7 +1427,7 @@ public:
   GLboolean IsTexture(GLuint texture)
   {
     LOG_GL("IsTexture %d\n", texture);
-    GLboolean val = CHECK_GL( *this, mGlAbstraction.IsTexture(texture) );
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsTexture(texture) );
     return val;
   }
 
@@ -1345,7 +1437,7 @@ public:
   GLboolean IsTransformFeedback(GLuint id)
   {
     LOG_GL("IsTransformFeedback %u\n", id);
-    GLboolean val = CHECK_GL( *this, mGlAbstraction.IsTransformFeedback(id) );
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsTransformFeedback(id) );
     return val;
   }
 
@@ -1355,7 +1447,7 @@ public:
   void LineWidth(GLfloat width)
   {
     LOG_GL("LineWidth %f\n", width);
-    CHECK_GL( *this, mGlAbstraction.LineWidth(width) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.LineWidth(width) );
   }
 
   /**
@@ -1364,7 +1456,7 @@ public:
   void PauseTransformFeedback()
   {
     LOG_GL("PauseTransformFeedback\n");
-    CHECK_GL( *this, mGlAbstraction.PauseTransformFeedback() );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.PauseTransformFeedback() );
   }
 
   /**
@@ -1373,7 +1465,7 @@ public:
   void PixelStorei(GLenum pname, GLint param)
   {
     LOG_GL("PixelStorei %x %d\n", pname, param);
-    CHECK_GL( *this, mGlAbstraction.PixelStorei(pname, param) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.PixelStorei(pname, param) );
   }
 
   /**
@@ -1382,7 +1474,7 @@ public:
   void PolygonOffset(GLfloat factor, GLfloat units)
   {
     LOG_GL("PolygonOffset %f %f\n", factor, units);
-    CHECK_GL( *this, mGlAbstraction.PolygonOffset(factor, units) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.PolygonOffset(factor, units) );
   }
 
   /**
@@ -1391,7 +1483,7 @@ public:
   void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
   {
     LOG_GL("ReadPixels %d %d %d %d %x %x\n", x, y, width, height, format, type);
-    CHECK_GL( *this, mGlAbstraction.ReadPixels(x, y, width, height, format, type, pixels) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.ReadPixels(x, y, width, height, format, type, pixels) );
   }
 
   /**
@@ -1400,7 +1492,7 @@ public:
   void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
   {
     LOG_GL("RenderbufferStorage %x %x %d %d\n", target, internalformat, width, height);
-    CHECK_GL( *this, mGlAbstraction.RenderbufferStorage(target, internalformat, width, height) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.RenderbufferStorage(target, internalformat, width, height) );
   }
 
   /**
@@ -1409,7 +1501,7 @@ public:
   void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
   {
     LOG_GL("RenderbufferStorageMultisample %x %u %x %d %d\n", target, samples, internalformat, width, height);
-    CHECK_GL( *this, mGlAbstraction.RenderbufferStorageMultisample(target, samples, internalformat, width, height) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.RenderbufferStorageMultisample(target, samples, internalformat, width, height) );
   }
 
   /**
@@ -1418,7 +1510,7 @@ public:
   void ResumeTransformFeedback()
   {
     LOG_GL("ResumeTransformFeedback\n");
-    CHECK_GL( *this, mGlAbstraction.ResumeTransformFeedback() );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.ResumeTransformFeedback() );
   }
 
   /**
@@ -1427,7 +1519,7 @@ public:
   void SampleCoverage(GLclampf value, GLboolean invert)
   {
     LOG_GL("SampleCoverage %f %s\n", value, invert ? "True" : "False");
-    CHECK_GL( *this, mGlAbstraction.SampleCoverage(value, invert) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.SampleCoverage(value, invert) );
   }
 
   /**
@@ -1436,7 +1528,7 @@ public:
   void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
   {
     LOG_GL("Scissor %d %d %d %d\n", x, y, width, height);
-    CHECK_GL( *this, mGlAbstraction.Scissor(x, y, width, height) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.Scissor(x, y, width, height) );
   }
 
   /**
@@ -1444,8 +1536,15 @@ public:
    */
   void StencilFunc(GLenum func, GLint ref, GLuint mask)
   {
-    LOG_GL("StencilFunc %x %d %d\n", func, ref, mask);
-    CHECK_GL( *this, mGlAbstraction.StencilFunc(func, ref, mask) );
+    if( ( func != mStencilFunc ) || ( ref != mStencilFuncRef ) || ( mask != mStencilFuncMask ) )
+    {
+      mStencilFunc = func;
+      mStencilFuncRef = ref;
+      mStencilFuncMask = mask;
+
+      LOG_GL("StencilFunc %x %d %d\n", func, ref, mask);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.StencilFunc(func, ref, mask) );
+    }
   }
 
   /**
@@ -1454,7 +1553,7 @@ public:
   void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
   {
     LOG_GL("StencilFuncSeparate %x %x %d %d\n", face, func, ref, mask);
-    CHECK_GL( *this, mGlAbstraction.StencilFuncSeparate(face, func, ref, mask) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.StencilFuncSeparate(face, func, ref, mask) );
   }
 
   /**
@@ -1467,7 +1566,7 @@ public:
       mStencilMask = mask;
 
       LOG_GL("StencilMask %d\n", mask);
-      CHECK_GL( *this, mGlAbstraction.StencilMask(mask) );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.StencilMask(mask) );
     }
   }
 
@@ -1477,7 +1576,7 @@ public:
   void StencilMaskSeparate(GLenum face, GLuint mask)
   {
     LOG_GL("StencilMaskSeparate %x %d\n", face, mask);
-    CHECK_GL( *this, mGlAbstraction.StencilMaskSeparate(face, mask) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.StencilMaskSeparate(face, mask) );
   }
 
   /**
@@ -1485,8 +1584,15 @@ public:
    */
   void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
   {
-    LOG_GL("StencilOp %x %x %x\n", fail, zfail, zpass);
-    CHECK_GL( *this, mGlAbstraction.StencilOp(fail, zfail, zpass) );
+    if( ( fail != mStencilOpFail ) || ( zfail != mStencilOpDepthFail ) || ( zpass != mStencilOpDepthPass ) )
+    {
+      mStencilOpFail = fail;
+      mStencilOpDepthFail = zfail;
+      mStencilOpDepthPass = zpass;
+
+      LOG_GL("StencilOp %x %x %x\n", fail, zfail, zpass);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.StencilOp(fail, zfail, zpass) );
+    }
   }
 
   /**
@@ -1495,7 +1601,7 @@ public:
   void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
   {
     LOG_GL("StencilOpSeparate %x %x %x %x\n", face, fail, zfail, zpass);
-    CHECK_GL( *this, mGlAbstraction.StencilOpSeparate(face, fail, zfail, zpass) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.StencilOpSeparate(face, fail, zfail, zpass) );
   }
 
   /**
@@ -1505,7 +1611,7 @@ public:
                   GLint border, GLenum format, GLenum type, const void* pixels)
   {
     LOG_GL("TexImage2D %x %d %d %dx%d %d %x %x %p\n", target, level, internalformat, width, height, border, format, type, pixels);
-    CHECK_GL( *this, mGlAbstraction.TexImage2D(target, level, internalformat, width, height, border, format, type, pixels) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexImage2D(target, level, internalformat, width, height, border, format, type, pixels) );
   }
 
   /**
@@ -1515,7 +1621,7 @@ public:
                   GLint border, GLenum format, GLenum type, const void* pixels)
   {
     LOG_GL("TexImage3D %x %d %d %dx%dx%d %d %x %x %p\n", target, level, internalformat, width, height, depth, border, format, type, pixels);
-    CHECK_GL( *this, mGlAbstraction.TexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels) );
   }
 
   /**
@@ -1524,7 +1630,7 @@ public:
   void TexParameterf(GLenum target, GLenum pname, GLfloat param)
   {
     LOG_GL("TexParameterf %x %x %f\n", target, pname, param);
-    CHECK_GL( *this, mGlAbstraction.TexParameterf(target, pname, param) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexParameterf(target, pname, param) );
   }
 
   /**
@@ -1533,7 +1639,7 @@ public:
   void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
   {
     LOG_GL("TexParameterfv %x %x\n", target, pname);
-    CHECK_GL( *this, mGlAbstraction.TexParameterfv(target, pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexParameterfv(target, pname, params) );
   }
 
   /**
@@ -1542,7 +1648,7 @@ public:
   void TexParameteri(GLenum target, GLenum pname, GLint param)
   {
     LOG_GL("TexParameteri %x %x %d\n", target, pname, param);
-    CHECK_GL( *this, mGlAbstraction.TexParameteri(target, pname, param) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexParameteri(target, pname, param) );
   }
 
   /**
@@ -1551,7 +1657,7 @@ public:
   void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
   {
     LOG_GL("TexParameteriv %x %x\n", target, pname);
-    CHECK_GL( *this, mGlAbstraction.TexParameteriv(target, pname, params) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexParameteriv(target, pname, params) );
   }
 
   /**
@@ -1561,7 +1667,7 @@ public:
                      GLenum format, GLenum type, const void* pixels)
   {
     LOG_GL("TexSubImage2D %x %d %d %d %d %d %x %x %p\n", target, level, xoffset, yoffset, width, height, format, type, pixels);
-    CHECK_GL( *this, mGlAbstraction.TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels) );
   }
 
   /**
@@ -1572,7 +1678,7 @@ public:
                      GLenum format, GLenum type, const void* pixels)
   {
     LOG_GL("TexSubImage3D %x %d %d %d %d %d %d %d %x %x %p\n", target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
-    CHECK_GL( *this, mGlAbstraction.TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) );
   }
 
   /**
@@ -1581,7 +1687,7 @@ public:
   GLboolean UnmapBuffer(GLenum target)
   {
     LOG_GL("UnmapBuffer %x \n", target);
-    GLboolean val = CHECK_GL( *this, mGlAbstraction.UnmapBuffer(target) );
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.UnmapBuffer(target) );
     return val;
   }
   /**
@@ -1591,11 +1697,15 @@ public:
   {
     // check if its same as already set
     Rect<int> newViewport( x, y, width, height );
-    if( mViewPort != newViewport )
+
+    // Temporarily disable the viewport caching, as the implementation of GLES driver in Tizen platform
+    // share a global viewport between multiple contexts, therefore glViewport has to be called every
+    // time after glBindFramebuffer regardless of the same vewport size in the same context.
+//    if( mViewPort != newViewport )
     {
       // set new one
       LOG_GL("Viewport %d %d %d %d\n", x, y, width, height);
-      CHECK_GL( *this, mGlAbstraction.Viewport(x, y, width, height) );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.Viewport(x, y, width, height) );
       mViewPort = newViewport; // remember new one
     }
   }
@@ -1610,154 +1720,35 @@ public:
   }
 
   /**
-   * Get the number of supported program binary formats
-   * @return The number of supported program binary formats
-   */
-  GLint CachedNumberOfProgramBinaryFormats() const
-  {
-    return mProgramBinaryFormats.size();
-  }
-
-  /**
-   * Get a supported program binary format
-   * @param[in] formatIndex The index of the format to return (default: 0)
-   * @return A supported program binary format
-   */
-  GLint CachedProgramBinaryFormat( const unsigned int formatIndex = 0 ) const
-  {
-    DALI_ASSERT_ALWAYS( formatIndex < mProgramBinaryFormats.size() && "formatIndex out of bounds");
-
-    return mProgramBinaryFormats[ formatIndex ];
-  }
-
-  /**
-   * @return current program
-   */
-  const Program* GetCurrentProgram() const
-  {
-    return mCurrentProgram;
-  }
-
-  /**
-   * Set current program
-   * @param [in] program that is in use
-   */
-  void SetCurrentProgram( Program* program )
-  {
-    mCurrentProgram = program;
-  }
-
-  /**
-   * Reset the program matrices
-   */
-  void ResetProgramMatrices();
-
-  /**
-   * Get a cached program
-   * @param [in] hash value
-   * @return pointer to the program
-   */
-  Program* GetCachedProgram( std::size_t hash ) const;
-
-  /**
-   * Cache a program
-   * @param [in] hash value
-   * @param [in] pointer to the program
-   */
-  void CacheProgram( std::size_t hash, Program* pointer );
-
-  /**
    * Get the current viewport.
    * @return Viewport rectangle.
    */
   const Rect< int >& GetViewport();
 
-#ifdef DEBUG_ENABLED
-
-  /// Switch debug level to Concise to disable, General to enable. Note, enabling snapshot logging will do this on the fly.
-  static Debug::Filter *gGlLogFilter;
-
-#endif // DEBUG_ENABLED
-
-
-  /**
-   * Set the frame count of render thread
-   */
-  inline void SetFrameCount(unsigned int frameCount)
-  {
-    mFrameCount = frameCount;
-  }
-
-  /**
-   * Get the frame count
-   */
-  inline unsigned int GetFrameCount()
-  {
-    return mFrameCount;
-  }
-
-  /**
-   * Increment the count of culled renderers
-   */
-  inline void IncrementCulledCount()
-  {
-    mCulledCount++;
-  }
-
-  /**
-   * Clear the count of culled renderers
-   */
-  inline void ClearCulledCount()
-  {
-    mCulledCount = 0;
-  }
-
-  /**
-   * Get the count of culled renderers in this frame
-   */
-  inline unsigned int GetCulledCount()
-  {
-    return mCulledCount;
-  }
-
-  /**
-   * Increment the count of culled renderers
-   */
-  inline void IncrementRendererCount()
-  {
-    mRendererCount++;
-  }
+private: // Implementation
 
   /**
-   * Clear the count of image renderers
+   * @return true if next draw operation will write to depth buffer
    */
-  inline void ClearRendererCount()
+  bool DepthBufferWriteEnabled() const
   {
-    mRendererCount = 0;
+    return mDepthBufferEnabled && mDepthMaskEnabled;
   }
 
   /**
-   * Get the count of image renderers in this frame
+   * @return true if next draw operation will write to stencil buffer
    */
-  inline unsigned int GetRendererCount()
+  bool StencilBufferWriteEnabled() const
   {
-    return mRendererCount;
+    return mStencilBufferEnabled && ( mStencilMask > 0 );
   }
 
-
-private: // Implementation
-
   /**
    * Flushes vertex attribute location changes to the driver
    */
   void FlushVertexAttributeLocations();
 
   /**
-   * Reset the cached internal vertex attribute state
-   */
-  void ResetVertexAttributeState();
-
-  /**
    * Either enables or disables a vertex attribute location in the cache
    * The cahnges won't take affect until FlushVertexAttributeLocations is called
    * @param location attribute location
@@ -1768,7 +1759,7 @@ private: // Implementation
   /**
    * Sets the initial GL state.
    */
-  void ResetGlState();
+  void InitializeGlState();
 
 private: // Data
 
@@ -1780,15 +1771,16 @@ private: // Data
   bool mColorMask;
   GLuint mStencilMask;
   bool mBlendEnabled;
-  bool mDepthTestEnabled;
+  bool mDepthBufferEnabled;
   bool mDepthMaskEnabled;
   bool mDitherEnabled;
   bool mPolygonOffsetFillEnabled;
   bool mSampleAlphaToCoverageEnabled;
   bool mSampleCoverageEnabled;
   bool mScissorTestEnabled;
-  bool mStencilTestEnabled;
+  bool mStencilBufferEnabled;
   bool mClearColorSet;
+  bool mUsingDefaultBlendColor;
 
   // glBindBuffer() state
   GLuint mBoundArrayBufferId;        ///< The ID passed to glBindBuffer(GL_ARRAY_BUFFER)
@@ -1796,11 +1788,11 @@ private: // Data
   GLuint mBoundTransformFeedbackBufferId; ///< The ID passed to glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER)
 
   // glBindTexture() state
-  unsigned int mActiveTextureUnit;
-  std::vector<GLuint> mBound2dTextureId;  ///< The ID passed to glBindTexture(GL_TEXTURE_2D)
+  TextureUnit mActiveTextureUnit;
+  GLuint mBoundTextureId[ MAX_TEXTURE_UNITS ];  ///< The ID passed to glBindTexture()
 
   // glBlendColor() state
-  bool mUsingDefaultBlendColor;
+  Vector4 mBlendColor; ///< Blend color
 
   // glBlendFuncSeparate() state
   GLenum mBlendFuncSeparateSrcRGB;   ///< The srcRGB parameter passed to glBlendFuncSeparate()
@@ -1812,14 +1804,21 @@ private: // Data
   GLenum mBlendEquationSeparateModeRGB;    ///< Controls RGB blend mode
   GLenum mBlendEquationSeparateModeAlpha;  ///< Controls Alpha blend mode
 
+  // glStencilFunc() and glStencilOp() state.
+  GLenum mStencilFunc;
+  GLint mStencilFuncRef;
+  GLuint mStencilFuncMask;
+  GLenum mStencilOpFail;
+  GLenum mStencilOpDepthFail;
+  GLenum mStencilOpDepthPass;
+
+  GLenum mDepthFunction;  ///The depth function
+
   GLint mMaxTextureSize;      ///< return value from GetIntegerv(GL_MAX_TEXTURE_SIZE)
-  GLint mMaxTextureUnits;     ///< return value from GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
   Vector4 mClearColor;        ///< clear color
 
-  std::vector<GLint>  mProgramBinaryFormats; ///< array of supported program binary formats
-
   // Face culling mode
-  CullFaceMode mCullFaceMode;
+  Dali::FaceCullingMode::Type mCullFaceMode;
 
   // cached viewport size
   Rect< int > mViewPort;
@@ -1828,16 +1827,13 @@ private: // Data
   bool mVertexAttributeCachedState[ MAX_ATTRIBUTE_CACHE_SIZE ];    ///< Value cache for Enable Vertex Attribute
   bool mVertexAttributeCurrentState[ MAX_ATTRIBUTE_CACHE_SIZE ];   ///< Current state on the driver for Enable Vertex Attribute
 
-  Program* mCurrentProgram;
-  typedef std::map< std::size_t, Program* > ProgramContainer;
-  ProgramContainer mProgramCache; ///< Cache of shader programs
-  unsigned int mFrameCount;       ///< Number of render frames
-  unsigned int mCulledCount;      ///< Number of culled renderers per frame
-  unsigned int mRendererCount;    ///< Number of image renderers per frame
+  FrameBufferStateCache mFrameBufferStateCache;   ///< frame buffer state cache
+
+  std::vector< Context* >* mSceneContexts;      ///< The pointer of the container of contexts for surface rendering
 };
 
 } // namespace Internal
 
 } // namespace Dali
 
-#endif // __DALI_INTERNAL_CONTEXT_H__
+#endif // DALI_INTERNAL_CONTEXT_H