Makes the State struct a member of Context, rather than its parent.
Signed-off-by: Andrew Lewycky
Signed-off-by: Daniel Koch

Author:    Shannon Woods

git-svn-id: https://angleproject.googlecode.com/svn/trunk@226 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 0ba369a..83a8d90 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -37,70 +37,70 @@
     : mConfig(config)
 {
     setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-    depthClearValue = 1.0f;
-    stencilClearValue = 0;
+    mState.depthClearValue = 1.0f;
+    mState.stencilClearValue = 0;
 
-    cullFace = false;
-    cullMode = GL_BACK;
-    frontFace = GL_CCW;
-    depthTest = false;
-    depthFunc = GL_LESS;
-    blend = false;
-    sourceBlendRGB = GL_ONE;
-    sourceBlendAlpha = GL_ONE;
-    destBlendRGB = GL_ZERO;
-    destBlendAlpha = GL_ZERO;
-    blendEquationRGB = GL_FUNC_ADD;
-    blendEquationAlpha = GL_FUNC_ADD;
-    blendColor.red = 0;
-    blendColor.green = 0;
-    blendColor.blue = 0;
-    blendColor.alpha = 0;
-    stencilTest = false;
-    stencilFunc = GL_ALWAYS;
-    stencilRef = 0;
-    stencilMask = -1;
-    stencilWritemask = -1;
-    stencilBackFunc = GL_ALWAYS;
-    stencilBackRef = 0;
-    stencilBackMask = - 1;
-    stencilBackWritemask = -1;
-    stencilFail = GL_KEEP;
-    stencilPassDepthFail = GL_KEEP;
-    stencilPassDepthPass = GL_KEEP;
-    stencilBackFail = GL_KEEP;
-    stencilBackPassDepthFail = GL_KEEP;
-    stencilBackPassDepthPass = GL_KEEP;
-    polygonOffsetFill = false;
-    polygonOffsetFactor = 0.0f;
-    polygonOffsetUnits = 0.0f;
-    sampleAlphaToCoverage = false;
-    sampleCoverage = false;
-    sampleCoverageValue = 1.0f;
-    sampleCoverageInvert = GL_FALSE;
-    scissorTest = false;
-    dither = true;
-    generateMipmapHint = GL_DONT_CARE;
+    mState.cullFace = false;
+    mState.cullMode = GL_BACK;
+    mState.frontFace = GL_CCW;
+    mState.depthTest = false;
+    mState.depthFunc = GL_LESS;
+    mState.blend = false;
+    mState.sourceBlendRGB = GL_ONE;
+    mState.sourceBlendAlpha = GL_ONE;
+    mState.destBlendRGB = GL_ZERO;
+    mState.destBlendAlpha = GL_ZERO;
+    mState.blendEquationRGB = GL_FUNC_ADD;
+    mState.blendEquationAlpha = GL_FUNC_ADD;
+    mState.blendColor.red = 0;
+    mState.blendColor.green = 0;
+    mState.blendColor.blue = 0;
+    mState.blendColor.alpha = 0;
+    mState.stencilTest = false;
+    mState.stencilFunc = GL_ALWAYS;
+    mState.stencilRef = 0;
+    mState.stencilMask = -1;
+    mState.stencilWritemask = -1;
+    mState.stencilBackFunc = GL_ALWAYS;
+    mState.stencilBackRef = 0;
+    mState.stencilBackMask = - 1;
+    mState.stencilBackWritemask = -1;
+    mState.stencilFail = GL_KEEP;
+    mState.stencilPassDepthFail = GL_KEEP;
+    mState.stencilPassDepthPass = GL_KEEP;
+    mState.stencilBackFail = GL_KEEP;
+    mState.stencilBackPassDepthFail = GL_KEEP;
+    mState.stencilBackPassDepthPass = GL_KEEP;
+    mState.polygonOffsetFill = false;
+    mState.polygonOffsetFactor = 0.0f;
+    mState.polygonOffsetUnits = 0.0f;
+    mState.sampleAlphaToCoverage = false;
+    mState.sampleCoverage = false;
+    mState.sampleCoverageValue = 1.0f;
+    mState.sampleCoverageInvert = GL_FALSE;
+    mState.scissorTest = false;
+    mState.dither = true;
+    mState.generateMipmapHint = GL_DONT_CARE;
 
-    lineWidth = 1.0f;
+    mState.lineWidth = 1.0f;
 
-    viewportX = 0;
-    viewportY = 0;
-    viewportWidth = config->mDisplayMode.Width;
-    viewportHeight = config->mDisplayMode.Height;
-    zNear = 0.0f;
-    zFar = 1.0f;
+    mState.viewportX = 0;
+    mState.viewportY = 0;
+    mState.viewportWidth = config->mDisplayMode.Width;
+    mState.viewportHeight = config->mDisplayMode.Height;
+    mState.zNear = 0.0f;
+    mState.zFar = 1.0f;
 
-    scissorX = 0;
-    scissorY = 0;
-    scissorWidth = config->mDisplayMode.Width;
-    scissorHeight = config->mDisplayMode.Height;
+    mState.scissorX = 0;
+    mState.scissorY = 0;
+    mState.scissorWidth = config->mDisplayMode.Width;
+    mState.scissorHeight = config->mDisplayMode.Height;
 
-    colorMaskRed = true;
-    colorMaskGreen = true;
-    colorMaskBlue = true;
-    colorMaskAlpha = true;
-    depthMask = true;
+    mState.colorMaskRed = true;
+    mState.colorMaskGreen = true;
+    mState.colorMaskBlue = true;
+    mState.colorMaskAlpha = true;
+    mState.depthMask = true;
 
     // [OpenGL ES 2.0.24] section 3.7 page 83:
     // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
@@ -115,9 +115,9 @@
     mDepthbufferZero = NULL;
     mStencilbufferZero = NULL;
 
-    activeSampler = 0;
-    arrayBuffer = 0;
-    elementArrayBuffer = 0;
+    mState.activeSampler = 0;
+    mState.arrayBuffer = 0;
+    mState.elementArrayBuffer = 0;
     bindTextureCubeMap(0);
     bindTexture2D(0);
     bindFramebuffer(0);
@@ -127,7 +127,7 @@
     {
         for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
         {
-            samplerTexture[type][sampler] = 0;
+            mState.samplerTexture[type][sampler] = 0;
         }
     }
 
@@ -136,10 +136,10 @@
         mIncompleteTextures[type] = NULL;
     }
 
-    currentProgram = 0;
+    mState.currentProgram = 0;
 
-    packAlignment = 4;
-    unpackAlignment = 4;
+    mState.packAlignment = 4;
+    mState.unpackAlignment = 4;
 
     mBufferBackEnd = NULL;
     mVertexDataManager = NULL;
@@ -157,7 +157,7 @@
 
 Context::~Context()
 {
-    currentProgram = 0;
+    mState.currentProgram = 0;
 
     for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
     {
@@ -237,17 +237,17 @@
     framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
     framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
 
-    if(!mHasBeenCurrent)
+    if (!mHasBeenCurrent)
     {
-        viewportX = 0;
-        viewportY = 0;
-        viewportWidth = surface->getWidth();
-        viewportHeight = surface->getHeight();
+        mState.viewportX = 0;
+        mState.viewportY = 0;
+        mState.viewportWidth = surface->getWidth();
+        mState.viewportHeight = surface->getHeight();
 
-        scissorX = 0;
-        scissorY = 0;
-        scissorWidth = surface->getWidth();
-        scissorHeight = surface->getHeight();
+        mState.scissorX = 0;
+        mState.scissorY = 0;
+        mState.scissorWidth = surface->getWidth();
+        mState.scissorHeight = surface->getHeight();
 
         mHasBeenCurrent = true;
     }
@@ -276,20 +276,314 @@
 
 void Context::setClearColor(float red, float green, float blue, float alpha)
 {
-    colorClearValue.red = red;
-    colorClearValue.green = green;
-    colorClearValue.blue = blue;
-    colorClearValue.alpha = alpha;
+    mState.colorClearValue.red = red;
+    mState.colorClearValue.green = green;
+    mState.colorClearValue.blue = blue;
+    mState.colorClearValue.alpha = alpha;
 }
 
 void Context::setClearDepth(float depth)
 {
-    depthClearValue = depth;
+    mState.depthClearValue = depth;
 }
 
 void Context::setClearStencil(int stencil)
 {
-    stencilClearValue = stencil;
+    mState.stencilClearValue = stencil;
+}
+
+void Context::setCullFace(bool enabled)
+{
+    mState.cullFace = enabled;
+}
+
+bool Context::isCullFaceEnabled() const
+{
+    return mState.cullFace;
+}
+
+void Context::setCullMode(GLenum mode)
+{
+    mState.cullMode = mode;
+}
+
+void Context::setFrontFace(GLenum front)
+{
+    mState.frontFace = front;
+}
+
+void Context::setDepthTest(bool enabled)
+{
+    mState.depthTest = enabled;
+}
+
+bool Context::isDepthTestEnabled() const
+{
+    return mState.depthTest;
+}
+
+void Context::setDepthFunc(GLenum depthFunc)
+{
+    mState.depthFunc = depthFunc;
+}
+
+void Context::setDepthRange(float zNear, float zFar)
+{
+    mState.zNear = zNear;
+    mState.zFar = zFar;
+}
+
+void Context::setBlend(bool enabled)
+{
+    mState.blend = enabled;
+}
+
+bool Context::isBlendEnabled() const
+{
+    return mState.blend;
+}
+
+void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
+{
+    mState.sourceBlendRGB = sourceRGB;
+    mState.destBlendRGB = destRGB;
+    mState.sourceBlendAlpha = sourceAlpha;
+    mState.destBlendAlpha = destAlpha;
+}
+
+void Context::setBlendColor(float red, float green, float blue, float alpha)
+{
+    mState.blendColor.red = red;
+    mState.blendColor.green = green;
+    mState.blendColor.blue = blue;
+    mState.blendColor.alpha = alpha;
+}
+
+void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
+{
+    mState.blendEquationRGB = rgbEquation;
+    mState.blendEquationAlpha = alphaEquation;
+}
+
+void Context::setStencilTest(bool enabled)
+{
+    mState.stencilTest = enabled;
+}
+
+bool Context::isStencilTestEnabled() const
+{
+    return mState.stencilTest;
+}
+
+void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
+{
+    mState.stencilFunc = stencilFunc;
+    mState.stencilRef = stencilRef;
+    mState.stencilMask = stencilMask;
+}
+
+void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
+{
+    mState.stencilBackFunc = stencilBackFunc;
+    mState.stencilBackRef = stencilBackRef;
+    mState.stencilBackMask = stencilBackMask;
+}
+
+void Context::setStencilWritemask(GLuint stencilWritemask)
+{
+    mState.stencilWritemask = stencilWritemask;
+}
+
+void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
+{
+    mState.stencilBackWritemask = stencilBackWritemask;
+}
+
+void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
+{
+    mState.stencilFail = stencilFail;
+    mState.stencilPassDepthFail = stencilPassDepthFail;
+    mState.stencilPassDepthPass = stencilPassDepthPass;
+}
+
+void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
+{
+    mState.stencilBackFail = stencilBackFail;
+    mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
+    mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
+}
+
+void Context::setPolygonOffsetFill(bool enabled)
+{
+    mState.polygonOffsetFill = enabled;
+}
+
+bool Context::isPolygonOffsetFillEnabled() const
+{
+    return mState.polygonOffsetFill;
+}
+
+void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
+{
+    mState.polygonOffsetFactor = factor;
+    mState.polygonOffsetUnits = units;
+}
+
+void Context::setSampleAlphaToCoverage(bool enabled)
+{
+    mState.sampleAlphaToCoverage = enabled;
+}
+
+bool Context::isSampleAlphaToCoverageEnabled() const
+{
+    return mState.sampleAlphaToCoverage;
+}
+
+void Context::setSampleCoverage(bool enabled)
+{
+    mState.sampleCoverage = enabled;
+}
+
+bool Context::isSampleCoverageEnabled() const
+{
+    return mState.sampleCoverage;
+}
+
+void Context::setSampleCoverageParams(GLclampf value, GLboolean invert)
+{
+    mState.sampleCoverageValue = value;
+    mState.sampleCoverageInvert = invert;
+}
+
+void Context::setScissorTest(bool enabled)
+{
+    mState.scissorTest = enabled;
+}
+
+bool Context::isScissorTestEnabled() const
+{
+    return mState.scissorTest;
+}
+
+void Context::setDither(bool enabled)
+{
+    mState.dither = enabled;
+}
+
+bool Context::isDitherEnabled() const
+{
+    return mState.dither;
+}
+
+void Context::setLineWidth(GLfloat width)
+{
+    mState.lineWidth = width;
+}
+
+void Context::setGenerateMipmapHint(GLenum hint)
+{
+    mState.generateMipmapHint = hint;
+}
+
+void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    mState.viewportX = x;
+    mState.viewportY = y;
+    mState.viewportWidth = width;
+    mState.viewportHeight = height;
+}
+
+void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+    mState.scissorX = x;
+    mState.scissorY = y;
+    mState.scissorWidth = width;
+    mState.scissorHeight = height;
+}
+
+void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
+{
+    mState.colorMaskRed = red;
+    mState.colorMaskGreen = green;
+    mState.colorMaskBlue = blue;
+    mState.colorMaskAlpha = alpha;
+}
+
+void Context::setDepthMask(bool mask)
+{
+    mState.depthMask = mask;
+}
+
+void Context::setActiveSampler(int active)
+{
+    mState.activeSampler = active;
+}
+
+GLuint Context::getFramebufferHandle() const
+{
+    return mState.framebuffer;
+}
+
+GLuint Context::getRenderbufferHandle() const
+{
+    return mState.renderbuffer;
+}
+
+GLuint Context::getArrayBufferHandle() const
+{
+    return mState.arrayBuffer;
+}
+
+void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
+{
+    mState.vertexAttribute[attribNum].mEnabled = enabled;
+}
+
+const AttributeState &Context::getVertexAttribState(unsigned int attribNum)
+{
+    return mState.vertexAttribute[attribNum];
+}
+
+void Context::setVertexAttribState(unsigned int attribNum, GLuint boundBuffer, GLint size, GLenum type, bool normalized,
+                                   GLsizei stride, const void *pointer)
+{
+    mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer;
+    mState.vertexAttribute[attribNum].mSize = size;
+    mState.vertexAttribute[attribNum].mType = type;
+    mState.vertexAttribute[attribNum].mNormalized = normalized;
+    mState.vertexAttribute[attribNum].mStride = stride;
+    mState.vertexAttribute[attribNum].mPointer = pointer;
+}
+
+const void *Context::getVertexAttribPointer(unsigned int attribNum) const
+{
+    return mState.vertexAttribute[attribNum].mPointer;
+}
+
+// returns entire set of attributes as a block
+const AttributeState *Context::getVertexAttribBlock()
+{
+    return mState.vertexAttribute;
+}
+
+void Context::setPackAlignment(GLint alignment)
+{
+    mState.packAlignment = alignment;
+}
+
+GLint Context::getPackAlignment() const
+{
+    return mState.packAlignment;
+}
+
+void Context::setUnpackAlignment(GLint alignment)
+{
+    mState.unpackAlignment = alignment;
+}
+
+GLint Context::getUnpackAlignment() const
+{
+    return mState.unpackAlignment;
 }
 
 // Returns an unused buffer name
@@ -427,7 +721,7 @@
 
     if (programObject != mProgramMap.end())
     {
-        if (program != currentProgram)
+        if (program != mState.currentProgram)
         {
             delete programObject->second;
             mProgramMap.erase(programObject);
@@ -489,7 +783,7 @@
         mBufferMap[buffer] = new Buffer(mBufferBackEnd);
     }
 
-    arrayBuffer = buffer;
+    mState.arrayBuffer = buffer;
 }
 
 void Context::bindElementArrayBuffer(unsigned int buffer)
@@ -499,7 +793,7 @@
         mBufferMap[buffer] = new Buffer(mBufferBackEnd);
     }
 
-    elementArrayBuffer = buffer;
+    mState.elementArrayBuffer = buffer;
 }
 
 void Context::bindTexture2D(GLuint texture)
@@ -509,9 +803,9 @@
         mTextureMap[texture] = new Texture2D(this);
     }
 
-    texture2D = texture;
+    mState.texture2D = texture;
 
-    samplerTexture[SAMPLER_2D][activeSampler] = texture;
+    mState.samplerTexture[SAMPLER_2D][mState.activeSampler] = texture;
 }
 
 void Context::bindTextureCubeMap(GLuint texture)
@@ -521,9 +815,9 @@
         mTextureMap[texture] = new TextureCubeMap(this);
     }
 
-    textureCubeMap = texture;
+    mState.textureCubeMap = texture;
 
-    samplerTexture[SAMPLER_CUBE][activeSampler] = texture;
+    mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler] = texture;
 }
 
 void Context::bindFramebuffer(GLuint framebuffer)
@@ -533,7 +827,7 @@
         mFramebufferMap[framebuffer] = new Framebuffer();
     }
 
-    this->framebuffer = framebuffer;
+    mState.framebuffer = framebuffer;
 }
 
 void Context::bindRenderbuffer(GLuint renderbuffer)
@@ -543,15 +837,15 @@
         mRenderbufferMap[renderbuffer] = new Renderbuffer();
     }
 
-    this->renderbuffer = renderbuffer;
+    mState.renderbuffer = renderbuffer;
 }
 
 void Context::useProgram(GLuint program)
 {
     Program *programObject = getCurrentProgram();
 
-    GLuint priorProgram = currentProgram;
-    currentProgram = program;               // Must switch before trying to delete, otherwise it only gets flagged.
+    GLuint priorProgram = mState.currentProgram;
+    mState.currentProgram = program;               // Must switch before trying to delete, otherwise it only gets flagged.
 
     if (programObject && programObject->isFlaggedForDeletion())
     {
@@ -585,8 +879,8 @@
 
 void Context::setRenderbuffer(Renderbuffer *buffer)
 {
-    delete mRenderbufferMap[renderbuffer];
-    mRenderbufferMap[renderbuffer] = buffer;
+    delete mRenderbufferMap[mState.renderbuffer];
+    mRenderbufferMap[mState.renderbuffer] = buffer;
 }
 
 Buffer *Context::getBuffer(unsigned int handle)
@@ -734,42 +1028,42 @@
 
 Buffer *Context::getArrayBuffer()
 {
-    return getBuffer(arrayBuffer);
+    return getBuffer(mState.arrayBuffer);
 }
 
 Buffer *Context::getElementArrayBuffer()
 {
-    return getBuffer(elementArrayBuffer);
+    return getBuffer(mState.elementArrayBuffer);
 }
 
 Program *Context::getCurrentProgram()
 {
-    return getProgram(currentProgram);
+    return getProgram(mState.currentProgram);
 }
 
 Texture2D *Context::getTexture2D()
 {
-    if (texture2D == 0)   // Special case: 0 refers to different initial textures based on the target
+    if (mState.texture2D == 0)   // Special case: 0 refers to different initial textures based on the target
     {
         return mTexture2DZero;
     }
 
-    return (Texture2D*)getTexture(texture2D);
+    return (Texture2D*)getTexture(mState.texture2D);
 }
 
 TextureCubeMap *Context::getTextureCubeMap()
 {
-    if (textureCubeMap == 0)   // Special case: 0 refers to different initial textures based on the target
+    if (mState.textureCubeMap == 0)   // Special case: 0 refers to different initial textures based on the target
     {
         return mTextureCubeMapZero;
     }
 
-    return (TextureCubeMap*)getTexture(textureCubeMap);
+    return (TextureCubeMap*)getTexture(mState.textureCubeMap);
 }
 
 Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
 {
-    GLuint texid = samplerTexture[type][sampler];
+    GLuint texid = mState.samplerTexture[type][sampler];
 
     if (texid == 0)
     {
@@ -786,31 +1080,31 @@
 
 Framebuffer *Context::getFramebuffer()
 {
-    return getFramebuffer(framebuffer);
+    return getFramebuffer(mState.framebuffer);
 }
 
 bool Context::getBooleanv(GLenum pname, GLboolean *params)
 {
     switch (pname)
     {
-      case GL_SHADER_COMPILER:          *params = GL_TRUE;                  break;
-      case GL_SAMPLE_COVERAGE_INVERT:   *params = sampleCoverageInvert;     break;
-      case GL_DEPTH_WRITEMASK:          *params = depthMask;                break;
+      case GL_SHADER_COMPILER:          *params = GL_TRUE;                          break;
+      case GL_SAMPLE_COVERAGE_INVERT:   *params = mState.sampleCoverageInvert;      break;
+      case GL_DEPTH_WRITEMASK:          *params = mState.depthMask;                 break;
       case GL_COLOR_WRITEMASK:
-        params[0] = colorMaskRed;
-        params[1] = colorMaskGreen;
-        params[2] = colorMaskBlue;
-        params[3] = colorMaskAlpha;
+        params[0] = mState.colorMaskRed;
+        params[1] = mState.colorMaskGreen;
+        params[2] = mState.colorMaskBlue;
+        params[3] = mState.colorMaskAlpha;
         break;
-      case GL_CULL_FACE:                *params = cullFace;
-      case GL_POLYGON_OFFSET_FILL:      *params = polygonOffsetFill;
-      case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = sampleAlphaToCoverage;
-      case GL_SAMPLE_COVERAGE:          *params = sampleCoverage;
-      case GL_SCISSOR_TEST:             *params = scissorTest;
-      case GL_STENCIL_TEST:             *params = stencilTest;
-      case GL_DEPTH_TEST:               *params = depthTest;
-      case GL_BLEND:                    *params = blend;
-      case GL_DITHER:                   *params = dither;
+      case GL_CULL_FACE:                *params = mState.cullFace;
+      case GL_POLYGON_OFFSET_FILL:      *params = mState.polygonOffsetFill;
+      case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
+      case GL_SAMPLE_COVERAGE:          *params = mState.sampleCoverage;
+      case GL_SCISSOR_TEST:             *params = mState.scissorTest;
+      case GL_STENCIL_TEST:             *params = mState.stencilTest;
+      case GL_DEPTH_TEST:               *params = mState.depthTest;
+      case GL_BLEND:                    *params = mState.blend;
+      case GL_DITHER:                   *params = mState.dither;
       default:
         return false;
     }
@@ -826,11 +1120,11 @@
     // case, this should make no difference to the calling application.
     switch (pname)
     {
-      case GL_LINE_WIDTH:               *params = lineWidth;            break;
-      case GL_SAMPLE_COVERAGE_VALUE:    *params = sampleCoverageValue;  break;
-      case GL_DEPTH_CLEAR_VALUE:        *params = depthClearValue;      break;
-      case GL_POLYGON_OFFSET_FACTOR:    *params = polygonOffsetFactor;  break;
-      case GL_POLYGON_OFFSET_UNITS:     *params = polygonOffsetUnits;   break;
+      case GL_LINE_WIDTH:               *params = mState.lineWidth;            break;
+      case GL_SAMPLE_COVERAGE_VALUE:    *params = mState.sampleCoverageValue;  break;
+      case GL_DEPTH_CLEAR_VALUE:        *params = mState.depthClearValue;      break;
+      case GL_POLYGON_OFFSET_FACTOR:    *params = mState.polygonOffsetFactor;  break;
+      case GL_POLYGON_OFFSET_UNITS:     *params = mState.polygonOffsetUnits;   break;
       case GL_ALIASED_LINE_WIDTH_RANGE:
         params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
         params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
@@ -840,20 +1134,20 @@
         params[1] = gl::ALIASED_POINT_SIZE_RANGE_MAX;
         break;
       case GL_DEPTH_RANGE:
-        params[0] = zNear;
-        params[1] = zFar;
+        params[0] = mState.zNear;
+        params[1] = mState.zFar;
         break;
       case GL_COLOR_CLEAR_VALUE:
-        params[0] = colorClearValue.red;
-        params[1] = colorClearValue.green;
-        params[2] = colorClearValue.blue;
-        params[3] = colorClearValue.alpha;
+        params[0] = mState.colorClearValue.red;
+        params[1] = mState.colorClearValue.green;
+        params[2] = mState.colorClearValue.blue;
+        params[3] = mState.colorClearValue.alpha;
         break;
       case GL_BLEND_COLOR:
-        params[0] = blendColor.red;
-        params[1] = blendColor.green;
-        params[2] = blendColor.blue;
-        params[3] = blendColor.alpha;
+        params[0] = mState.blendColor.red;
+        params[1] = mState.blendColor.green;
+        params[2] = mState.blendColor.blue;
+        params[3] = mState.blendColor.alpha;
         break;
       default:
         return false;
@@ -883,37 +1177,37 @@
       case GL_NUM_COMPRESSED_TEXTURE_FORMATS:   *params = 0;                                break;
       case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
       case GL_SHADER_BINARY_FORMATS:      /* no shader binary formats are supported */      break;
-      case GL_ARRAY_BUFFER_BINDING:             *params = arrayBuffer;              break;
-      case GL_ELEMENT_ARRAY_BUFFER_BINDING:     *params = elementArrayBuffer;       break;
-      case GL_FRAMEBUFFER_BINDING:              *params = framebuffer;              break;
-      case GL_RENDERBUFFER_BINDING:             *params = renderbuffer;             break;
-      case GL_CURRENT_PROGRAM:                  *params = currentProgram;           break;
-      case GL_PACK_ALIGNMENT:                   *params = packAlignment;            break;
-      case GL_UNPACK_ALIGNMENT:                 *params = unpackAlignment;          break;
-      case GL_GENERATE_MIPMAP_HINT:             *params = generateMipmapHint;       break;
-      case GL_ACTIVE_TEXTURE:                   *params = activeSampler;            break;
-      case GL_STENCIL_FUNC:                     *params = stencilFunc;              break;
-      case GL_STENCIL_REF:                      *params = stencilRef;               break;
-      case GL_STENCIL_VALUE_MASK:               *params = stencilMask;              break;
-      case GL_STENCIL_BACK_FUNC:                *params = stencilBackFunc;          break;
-      case GL_STENCIL_BACK_REF:                 *params = stencilBackRef;           break;
-      case GL_STENCIL_BACK_VALUE_MASK:          *params = stencilBackMask;          break;
-      case GL_STENCIL_FAIL:                     *params = stencilFail;              break;
-      case GL_STENCIL_PASS_DEPTH_FAIL:          *params = stencilPassDepthFail;     break;
-      case GL_STENCIL_PASS_DEPTH_PASS:          *params = stencilPassDepthPass;     break;
-      case GL_STENCIL_BACK_FAIL:                *params = stencilBackFail;          break;
-      case GL_STENCIL_BACK_PASS_DEPTH_FAIL:     *params = stencilBackPassDepthFail;     break;
-      case GL_STENCIL_BACK_PASS_DEPTH_PASS:     *params = stencilBackPassDepthPass;     break;
-      case GL_DEPTH_FUNC:                       *params = depthFunc;                    break;
-      case GL_BLEND_SRC_RGB:                    *params = sourceBlendRGB;               break;
-      case GL_BLEND_SRC_ALPHA:                  *params = sourceBlendAlpha;             break;
-      case GL_BLEND_DST_RGB:                    *params = destBlendRGB;                 break;
-      case GL_BLEND_DST_ALPHA:                  *params = destBlendAlpha;               break;
-      case GL_BLEND_EQUATION_RGB:               *params = blendEquationRGB;             break;
-      case GL_BLEND_EQUATION_ALPHA:             *params = blendEquationAlpha;           break;
-      case GL_STENCIL_WRITEMASK:                *params = stencilWritemask;             break;
-      case GL_STENCIL_BACK_WRITEMASK:           *params = stencilBackWritemask;         break;
-      case GL_STENCIL_CLEAR_VALUE:              *params = stencilClearValue;            break;
+      case GL_ARRAY_BUFFER_BINDING:             *params = mState.arrayBuffer;              break;
+      case GL_ELEMENT_ARRAY_BUFFER_BINDING:     *params = mState.elementArrayBuffer;       break;
+      case GL_FRAMEBUFFER_BINDING:              *params = mState.framebuffer;              break;
+      case GL_RENDERBUFFER_BINDING:             *params = mState.renderbuffer;             break;
+      case GL_CURRENT_PROGRAM:                  *params = mState.currentProgram;           break;
+      case GL_PACK_ALIGNMENT:                   *params = mState.packAlignment;            break;
+      case GL_UNPACK_ALIGNMENT:                 *params = mState.unpackAlignment;          break;
+      case GL_GENERATE_MIPMAP_HINT:             *params = mState.generateMipmapHint;       break;
+      case GL_ACTIVE_TEXTURE:                   *params = mState.activeSampler;            break;
+      case GL_STENCIL_FUNC:                     *params = mState.stencilFunc;              break;
+      case GL_STENCIL_REF:                      *params = mState.stencilRef;               break;
+      case GL_STENCIL_VALUE_MASK:               *params = mState.stencilMask;              break;
+      case GL_STENCIL_BACK_FUNC:                *params = mState.stencilBackFunc;          break;
+      case GL_STENCIL_BACK_REF:                 *params = mState.stencilBackRef;           break;
+      case GL_STENCIL_BACK_VALUE_MASK:          *params = mState.stencilBackMask;          break;
+      case GL_STENCIL_FAIL:                     *params = mState.stencilFail;              break;
+      case GL_STENCIL_PASS_DEPTH_FAIL:          *params = mState.stencilPassDepthFail;     break;
+      case GL_STENCIL_PASS_DEPTH_PASS:          *params = mState.stencilPassDepthPass;     break;
+      case GL_STENCIL_BACK_FAIL:                *params = mState.stencilBackFail;          break;
+      case GL_STENCIL_BACK_PASS_DEPTH_FAIL:     *params = mState.stencilBackPassDepthFail;     break;
+      case GL_STENCIL_BACK_PASS_DEPTH_PASS:     *params = mState.stencilBackPassDepthPass;     break;
+      case GL_DEPTH_FUNC:                       *params = mState.depthFunc;                    break;
+      case GL_BLEND_SRC_RGB:                    *params = mState.sourceBlendRGB;               break;
+      case GL_BLEND_SRC_ALPHA:                  *params = mState.sourceBlendAlpha;             break;
+      case GL_BLEND_DST_RGB:                    *params = mState.destBlendRGB;                 break;
+      case GL_BLEND_DST_ALPHA:                  *params = mState.destBlendAlpha;               break;
+      case GL_BLEND_EQUATION_RGB:               *params = mState.blendEquationRGB;             break;
+      case GL_BLEND_EQUATION_ALPHA:             *params = mState.blendEquationAlpha;           break;
+      case GL_STENCIL_WRITEMASK:                *params = mState.stencilWritemask;             break;
+      case GL_STENCIL_BACK_WRITEMASK:           *params = mState.stencilBackWritemask;         break;
+      case GL_STENCIL_CLEAR_VALUE:              *params = mState.stencilClearValue;            break;
       case GL_SUBPIXEL_BITS:                    *params = 4;                            break;
       case GL_MAX_TEXTURE_SIZE:                 *params = gl::MAX_TEXTURE_SIZE;             break;
       case GL_MAX_CUBE_MAP_TEXTURE_SIZE:        *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE;    break;
@@ -929,19 +1223,19 @@
         }
         break;
       case GL_VIEWPORT:
-        params[0] = viewportX;
-        params[1] = viewportY;
-        params[2] = viewportWidth;
-        params[3] = viewportHeight;
+        params[0] = mState.viewportX;
+        params[1] = mState.viewportY;
+        params[2] = mState.viewportWidth;
+        params[3] = mState.viewportHeight;
         break;
       case GL_SCISSOR_BOX:
-        params[0] = scissorX;
-        params[1] = scissorY;
-        params[2] = scissorWidth;
-        params[3] = scissorHeight;
+        params[0] = mState.scissorX;
+        params[1] = mState.scissorY;
+        params[2] = mState.scissorWidth;
+        params[3] = mState.scissorHeight;
         break;
-      case GL_CULL_FACE_MODE:                   *params = cullMode;                 break;
-      case GL_FRONT_FACE:                       *params = frontFace;                break;
+      case GL_CULL_FACE_MODE:                   *params = mState.cullMode;                 break;
+      case GL_FRONT_FACE:                       *params = mState.frontFace;                break;
       case GL_RED_BITS:
       case GL_GREEN_BITS:
       case GL_BLUE_BITS:
@@ -998,24 +1292,24 @@
         break;
       case GL_TEXTURE_BINDING_2D:
         {
-            if (activeSampler < 0 || activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
+            if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
             {
                 error(GL_INVALID_OPERATION);
                 return false;
             }
 
-            *params = samplerTexture[SAMPLER_2D][activeSampler];
+            *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler];
         }
         break;
       case GL_TEXTURE_BINDING_CUBE_MAP:
         {
-            if (activeSampler < 0 || activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
+            if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
             {
                 error(GL_INVALID_OPERATION);
                 return false;
             }
 
-            *params = samplerTexture[SAMPLER_CUBE][activeSampler];
+            *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler];
         }
         break;
       default:
@@ -1207,22 +1501,22 @@
     }
     else
     {
-        viewport.X = std::max(viewportX, 0);
-        viewport.Y = std::max(viewportY, 0);
-        viewport.Width = std::min(viewportWidth, (int)desc.Width - (int)viewport.X);
-        viewport.Height = std::min(viewportHeight, (int)desc.Height - (int)viewport.Y);
-        viewport.MinZ = clamp01(zNear);
-        viewport.MaxZ = clamp01(zFar);
+        viewport.X = std::max(mState.viewportX, 0);
+        viewport.Y = std::max(mState.viewportY, 0);
+        viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
+        viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
+        viewport.MinZ = clamp01(mState.zNear);
+        viewport.MaxZ = clamp01(mState.zFar);
     }
 
     device->SetViewport(&viewport);
 
-    if (scissorTest)
+    if (mState.scissorTest)
     {
-        RECT rect = {scissorX,
-                     scissorY,
-                     scissorX + scissorWidth,
-                     scissorY + scissorHeight};
+        RECT rect = {mState.scissorX,
+                     mState.scissorY,
+                     mState.scissorX + mState.scissorWidth,
+                     mState.scissorY + mState.scissorHeight};
 
         device->SetScissorRect(&rect);
         device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
@@ -1232,7 +1526,7 @@
         device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
     }
 
-    if (currentProgram)
+    if (mState.currentProgram)
     {
         Program *programObject = getCurrentProgram();
 
@@ -1241,21 +1535,23 @@
         programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
 
         GLint window = programObject->getUniformLocation("dx_Window");
-        GLfloat whxy[4] = {viewportWidth / 2.0f, viewportHeight / 2.0f, (float)viewportX + viewportWidth / 2.0f, (float)viewportY + viewportHeight / 2.0f};
+        GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f, 
+                          (float)mState.viewportX + mState.viewportWidth / 2.0f, 
+                          (float)mState.viewportY + mState.viewportHeight / 2.0f};
         programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
 
         GLint depth = programObject->getUniformLocation("dx_Depth");
-        GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
+        GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
         programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
 
         GLint near = programObject->getUniformLocation("gl_DepthRange.near");
-        programObject->setUniform1fv(near, 1, &zNear);
+        programObject->setUniform1fv(near, 1, &mState.zNear);
 
         GLint far = programObject->getUniformLocation("gl_DepthRange.far");
-        programObject->setUniform1fv(far, 1, &zFar);
+        programObject->setUniform1fv(far, 1, &mState.zFar);
 
         GLint diff = programObject->getUniformLocation("gl_DepthRange.diff");
-        GLfloat zDiff = zFar - zNear;
+        GLfloat zDiff = mState.zFar - mState.zNear;
         programObject->setUniform1fv(diff, 1, &zDiff);
     }
 
@@ -1269,60 +1565,62 @@
     Program *programObject = getCurrentProgram();
 
     GLint frontCCW = programObject->getUniformLocation("dx_FrontCCW");
-    GLint ccw = (frontFace == GL_CCW);
+    GLint ccw = (mState.frontFace == GL_CCW);
     programObject->setUniform1iv(frontCCW, 1, &ccw);
 
     GLint pointsOrLines = programObject->getUniformLocation("dx_PointsOrLines");
     GLint alwaysFront = !isTriangleMode(drawMode);
     programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
 
-    if (cullFace)
+    if (mState.cullFace)
     {
-        device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(cullMode, frontFace));
+        device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
     }
     else
     {
         device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
     }
 
-    if (depthTest)
+    if (mState.depthTest)
     {
         device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
-        device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(depthFunc));
+        device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
     }
     else
     {
         device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
     }
 
-    if (blend)
+    if (mState.blend)
     {
         device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
 
-        if (sourceBlendRGB != GL_CONSTANT_ALPHA && sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
-            destBlendRGB != GL_CONSTANT_ALPHA && destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
+        if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
+            mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
         {
-            device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(blendColor));
+            device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
         }
         else
         {
-            device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(blendColor.alpha),
-                                                                    unorm<8>(blendColor.alpha),
-                                                                    unorm<8>(blendColor.alpha),
-                                                                    unorm<8>(blendColor.alpha)));
+            device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
+                                                                    unorm<8>(mState.blendColor.alpha),
+                                                                    unorm<8>(mState.blendColor.alpha),
+                                                                    unorm<8>(mState.blendColor.alpha)));
         }
 
-        device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(sourceBlendRGB));
-        device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(destBlendRGB));
-        device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(blendEquationRGB));
+        device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
+        device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
+        device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
 
-        if (sourceBlendRGB != sourceBlendAlpha || destBlendRGB != destBlendAlpha || blendEquationRGB != blendEquationAlpha)
+        if (mState.sourceBlendRGB != mState.sourceBlendAlpha || 
+            mState.destBlendRGB != mState.destBlendAlpha || 
+            mState.blendEquationRGB != mState.blendEquationAlpha)
         {
             device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
 
-            device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(sourceBlendAlpha));
-            device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(destBlendAlpha));
-            device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(blendEquationAlpha));
+            device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
+            device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
+            device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
 
         }
         else
@@ -1335,7 +1633,7 @@
         device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
     }
 
-    if (stencilTest)
+    if (mState.stencilTest)
     {
         device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
         device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
@@ -1344,47 +1642,58 @@
         const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
         const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
         const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
-        if(stencilWritemask != stencilBackWritemask || stencilRef != stencilBackRef || stencilMask != stencilBackMask)
+        if (mState.stencilWritemask != mState.stencilBackWritemask || 
+            mState.stencilRef != mState.stencilBackRef || 
+            mState.stencilMask != mState.stencilBackMask)
         {
             ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
             return error(GL_INVALID_OPERATION);
         }
 
-        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWritemask);
-        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilFunc));
+        device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
+        device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 
+                               es2dx::ConvertComparison(mState.stencilFunc));
 
-        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilRef);   // FIXME: Clamp to range
-        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask);
+        device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilRef);   // FIXME: Clamp to range
+        device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
 
-        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilFail));
-        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilPassDepthFail));
-        device->SetRenderState(frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilPassDepthPass));
+        device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, 
+                               es2dx::ConvertStencilOp(mState.stencilFail));
+        device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, 
+                               es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
+        device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, 
+                               es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
 
-        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWritemask);
-        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, es2dx::ConvertComparison(stencilBackFunc));
+        device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
+        device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, 
+                               es2dx::ConvertComparison(mState.stencilBackFunc));
 
-        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, stencilBackRef);   // FIXME: Clamp to range
-        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilBackMask);
+        device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilBackRef);   // FIXME: Clamp to range
+        device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
 
-        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, es2dx::ConvertStencilOp(stencilBackFail));
-        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, es2dx::ConvertStencilOp(stencilBackPassDepthFail));
-        device->SetRenderState(frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, es2dx::ConvertStencilOp(stencilBackPassDepthPass));
+        device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, 
+                               es2dx::ConvertStencilOp(mState.stencilBackFail));
+        device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, 
+                               es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
+        device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, 
+                               es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
     }
     else
     {
         device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
     }
 
-    device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(colorMaskRed, colorMaskGreen, colorMaskBlue, colorMaskAlpha));
-    device->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE);
+    device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, 
+                                                                           mState.colorMaskBlue, mState.colorMaskAlpha));
+    device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
 
-    if (polygonOffsetFill)
+    if (mState.polygonOffsetFill)
     {
         gl::Depthbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
         if (depthbuffer)
         {
-            device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&polygonOffsetFactor));
-            float depthBias = ldexp(polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
+            device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
+            float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
             device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
         }
     }
@@ -1396,18 +1705,18 @@
 
     if (mConfig->mMultiSample != 0)
     {
-        if (sampleAlphaToCoverage)
+        if (mState.sampleAlphaToCoverage)
         {
             FIXME("Sample alpha to coverage is unimplemented.");
         }
 
-        if (sampleCoverage)
+        if (mState.sampleCoverage)
         {
             FIXME("Sample coverage is unimplemented.");
         }
     }
 
-    device->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
+    device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
 }
 
 // Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
@@ -1428,9 +1737,9 @@
 // Handle these cases here and return a pointer to the index data.
 const Index *Context::adjustIndexPointer(const void *indices)
 {
-    if (elementArrayBuffer)
+    if (mState.elementArrayBuffer)
     {
-        Buffer *buffer = getBuffer(elementArrayBuffer);
+        Buffer *buffer = getBuffer(mState.elementArrayBuffer);
         return reinterpret_cast<const Index*>(static_cast<unsigned char*>(buffer->data()) + reinterpret_cast<GLsizei>(indices));
     }
     else
@@ -1464,7 +1773,7 @@
 // Applies the indices and element array bindings to the Direct3D 9 device
 TranslatedIndexData Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type)
 {
-    TranslatedIndexData indexInfo = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(elementArrayBuffer), indices);
+    TranslatedIndexData indexInfo = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(mState.elementArrayBuffer), indices);
     mBufferBackEnd->setupIndicesPreDraw(indexInfo);
     return indexInfo;
 }
@@ -1589,7 +1898,7 @@
     unsigned char *dest = (unsigned char*)pixels;
     unsigned short *dest16 = (unsigned short*)pixels;
 
-    GLsizei outputPitch = ComputePitch(width, format, type, packAlignment);
+    GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
 
     for (int j = 0; j < rect.bottom - rect.top; j++)
     {
@@ -1717,7 +2026,7 @@
     if (mask & GL_DEPTH_BUFFER_BIT)
     {
         mask &= ~GL_DEPTH_BUFFER_BIT;
-        if (depthMask)
+        if (mState.depthMask)
         {
             flags |= D3DCLEAR_ZBUFFER;
         }
@@ -1750,22 +2059,25 @@
 
     applyRenderTarget(true);   // Clips the clear to the scissor rectangle but not the viewport
 
-    D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(colorClearValue.alpha), unorm<8>(colorClearValue.red), unorm<8>(colorClearValue.green), unorm<8>(colorClearValue.blue));
-    float depth = clamp01(depthClearValue);
-    int stencil = stencilClearValue & 0x000000FF;
+    D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha), 
+                                            unorm<8>(mState.colorClearValue.red), 
+                                            unorm<8>(mState.colorClearValue.green), 
+                                            unorm<8>(mState.colorClearValue.blue));
+    float depth = clamp01(mState.depthClearValue);
+    int stencil = mState.stencilClearValue & 0x000000FF;
 
     IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
 
     D3DSURFACE_DESC desc;
     renderTarget->GetDesc(&desc);
 
-    bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || colorMaskAlpha;
+    bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
 
     const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
-                                        (stencilWritemask & stencilUnmasked) != stencilUnmasked;
+                                        (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
     const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
-                                      !(colorMaskRed && colorMaskGreen &&
-                                        colorMaskBlue && alphaUnmasked);
+                                      !(mState.colorMaskRed && mState.colorMaskGreen &&
+                                        mState.colorMaskBlue && alphaUnmasked);
 
     if (needMaskedColorClear || needMaskedStencilClear)
     {
@@ -1780,10 +2092,10 @@
 
         if (flags & D3DCLEAR_TARGET)
         {
-            device->SetRenderState(D3DRS_COLORWRITEENABLE, (colorMaskRed   ? D3DCOLORWRITEENABLE_RED   : 0) |
-                                                           (colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
-                                                           (colorMaskBlue  ? D3DCOLORWRITEENABLE_BLUE  : 0) |
-                                                           (colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
+            device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed   ? D3DCOLORWRITEENABLE_RED   : 0) |
+                                                           (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
+                                                           (mState.colorMaskBlue  ? D3DCOLORWRITEENABLE_BLUE  : 0) |
+                                                           (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
         }
         else
         {
@@ -1796,7 +2108,7 @@
             device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
             device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
             device->SetRenderState(D3DRS_STENCILREF, stencil);
-            device->SetRenderState(D3DRS_STENCILWRITEMASK, stencilWritemask);
+            device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
             device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
             device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
             device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
@@ -1860,7 +2172,7 @@
 
 void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
 {
-    if (!currentProgram)
+    if (!mState.currentProgram)
     {
         return error(GL_INVALID_OPERATION);
     }
@@ -1902,12 +2214,12 @@
 
 void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
 {
-    if (!currentProgram)
+    if (!mState.currentProgram)
     {
         return error(GL_INVALID_OPERATION);
     }
 
-    if (!indices && !elementArrayBuffer)
+    if (!indices && !mState.elementArrayBuffer)
     {
         return error(GL_INVALID_OPERATION);
     }
@@ -2098,21 +2410,21 @@
     // If a buffer object is deleted while it is bound, all bindings to that object in the current context
     // (i.e. in the thread that called Delete-Buffers) are reset to zero.
 
-    if (arrayBuffer == buffer)
+    if (mState.arrayBuffer == buffer)
     {
-        arrayBuffer = 0;
+        mState.arrayBuffer = 0;
     }
 
-    if (elementArrayBuffer == buffer)
+    if (mState.elementArrayBuffer == buffer)
     {
-        elementArrayBuffer = 0;
+        mState.elementArrayBuffer = 0;
     }
 
     for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
     {
-        if (vertexAttribute[attribute].mBoundBuffer == buffer)
+        if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
         {
-            vertexAttribute[attribute].mBoundBuffer = 0;
+            mState.vertexAttribute[attribute].mBoundBuffer = 0;
         }
     }
 }
@@ -2127,9 +2439,9 @@
     {
         for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
         {
-            if (samplerTexture[type][sampler] == texture)
+            if (mState.samplerTexture[type][sampler] == texture)
             {
-                samplerTexture[type][sampler] = 0;
+                mState.samplerTexture[type][sampler] = 0;
             }
         }
     }
@@ -2153,7 +2465,7 @@
     // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
     // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
 
-    if (this->framebuffer == framebuffer)
+    if (mState.framebuffer == framebuffer)
     {
         bindFramebuffer(0);
     }
@@ -2165,7 +2477,7 @@
     // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
     // had been executed with the target RENDERBUFFER and name of zero.
 
-    if (this->renderbuffer == renderbuffer)
+    if (mState.renderbuffer == renderbuffer)
     {
         bindRenderbuffer(0);
     }
@@ -2229,7 +2541,7 @@
 
 bool Context::cullSkipsDraw(GLenum drawMode)
 {
-    return cullFace && cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
+    return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
 }
 
 bool Context::isTriangleMode(GLenum drawMode)
@@ -2255,10 +2567,10 @@
 {
     ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
 
-    vertexAttribute[index].mCurrentValue[0] = values[0];
-    vertexAttribute[index].mCurrentValue[1] = values[1];
-    vertexAttribute[index].mCurrentValue[2] = values[2];
-    vertexAttribute[index].mCurrentValue[3] = values[3];
+    mState.vertexAttribute[index].mCurrentValue[0] = values[0];
+    mState.vertexAttribute[index].mCurrentValue[1] = values[1];
+    mState.vertexAttribute[index].mCurrentValue[2] = values[2];
+    mState.vertexAttribute[index].mCurrentValue[3] = values[3];
 
     mVertexDataManager->dirtyCurrentValues();
 }
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index fa0ed7b..4372b0b 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -198,7 +198,7 @@
     GLint packAlignment;
 };
 
-class Context : public State
+class Context
 {
   public:
     Context(const egl::Config *config);
@@ -207,10 +207,95 @@
 
     void makeCurrent(egl::Display *display, egl::Surface *surface);
 
+    // State manipulation
     void setClearColor(float red, float green, float blue, float alpha);
+
     void setClearDepth(float depth);
+
     void setClearStencil(int stencil);
 
+    void setCullFace(bool enabled);
+    bool isCullFaceEnabled() const;
+
+    void setCullMode(GLenum mode);
+
+    void setFrontFace(GLenum front);
+
+    void setDepthTest(bool enabled);
+    bool isDepthTestEnabled() const;
+
+    void setDepthFunc(GLenum depthFunc);
+
+    void setDepthRange(float zNear, float zFar);
+    
+    void setBlend(bool enabled);
+    bool isBlendEnabled() const;
+
+    void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);
+    void setBlendColor(float red, float green, float blue, float alpha);
+    void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation);
+
+    void setStencilTest(bool enabled);
+    bool isStencilTestEnabled() const;
+
+    void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask);
+    void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask);
+    void setStencilWritemask(GLuint stencilWritemask);
+    void setStencilBackWritemask(GLuint stencilBackWritemask);
+    void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass);
+    void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass);
+
+    void setPolygonOffsetFill(bool enabled);
+    bool isPolygonOffsetFillEnabled() const;
+
+    void setPolygonOffsetParams(GLfloat factor, GLfloat units);
+
+    void setSampleAlphaToCoverage(bool enabled);
+    bool isSampleAlphaToCoverageEnabled() const;
+
+    void setSampleCoverage(bool enabled);
+    bool isSampleCoverageEnabled() const;
+
+    void setSampleCoverageParams(GLclampf value, GLboolean invert);
+
+    void setScissorTest(bool enabled);
+    bool isScissorTestEnabled() const;
+
+    void setDither(bool enabled);
+    bool isDitherEnabled() const;
+
+    void setLineWidth(GLfloat width);
+
+    void setGenerateMipmapHint(GLenum hint);
+
+    void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
+
+    void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height);
+
+    void setColorMask(bool red, bool green, bool blue, bool alpha);
+    void setDepthMask(bool mask);
+
+    void setActiveSampler(int active);
+
+    GLuint getFramebufferHandle() const;
+    GLuint getRenderbufferHandle() const;
+
+    GLuint getArrayBufferHandle() const;
+
+    void setVertexAttribEnabled(unsigned int attribNum, bool enabled);
+    const AttributeState &getVertexAttribState(unsigned int attribNum);
+    void setVertexAttribState(unsigned int attribNum, GLuint boundBuffer, GLint size, GLenum type,
+                              bool normalized, GLsizei stride, const void *pointer);
+    const void *getVertexAttribPointer(unsigned int attribNum) const;
+
+    const AttributeState *getVertexAttribBlock();
+
+    void setUnpackAlignment(GLint alignment);
+    GLint getUnpackAlignment() const;
+
+    void setPackAlignment(GLint alignment);
+    GLint getPackAlignment() const;
+
     GLuint createBuffer();
     GLuint createShader(GLenum type);
     GLuint createProgram();
@@ -311,6 +396,8 @@
 
     const egl::Config *const mConfig;
 
+    State   mState;
+
     Texture2D *mTexture2DZero;
     TextureCubeMap *mTextureCubeMapZero;
 
diff --git a/src/libGLESv2/geometry/VertexDataManager.cpp b/src/libGLESv2/geometry/VertexDataManager.cpp
index 4eb6199..1f646d1 100644
--- a/src/libGLESv2/geometry/VertexDataManager.cpp
+++ b/src/libGLESv2/geometry/VertexDataManager.cpp
@@ -85,7 +85,7 @@
 {
     ArrayTranslationHelper translationHelper(start, count);
 
-    return internalPreRenderValidate(mContext->vertexAttribute, activeAttribs(), start, start+count-1, &translationHelper, outAttribs);
+    return internalPreRenderValidate(mContext->getVertexAttribBlock(), activeAttribs(), start, start+count-1, &translationHelper, outAttribs);
 }
 
 GLenum VertexDataManager::preRenderValidate(const TranslatedIndexData &indexInfo,
@@ -93,7 +93,7 @@
 {
     IndexedTranslationHelper translationHelper(indexInfo.indices, indexInfo.minIndex, indexInfo.count);
 
-    return internalPreRenderValidate(mContext->vertexAttribute, activeAttribs(), indexInfo.minIndex, indexInfo.maxIndex, &translationHelper, outAttribs);
+    return internalPreRenderValidate(mContext->getVertexAttribBlock(), activeAttribs(), indexInfo.minIndex, indexInfo.maxIndex, &translationHelper, outAttribs);
 }
 
 GLenum VertexDataManager::internalPreRenderValidate(const AttributeState *attribs,
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 6199fc3..ec127bd 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -44,7 +44,7 @@
 
         if (context)
         {
-            context->activeSampler = texture - GL_TEXTURE0;
+            context->setActiveSampler(texture - GL_TEXTURE0);
         }
     }
     catch(std::bad_alloc&)
@@ -269,10 +269,7 @@
 
         if (context)
         {
-            context->blendColor.red = gl::clamp01(red);
-            context->blendColor.blue = gl::clamp01(blue);
-            context->blendColor.green = gl::clamp01(green);
-            context->blendColor.alpha = gl::clamp01(alpha);
+            context->setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha));
         }
     }
     catch(std::bad_alloc&)
@@ -316,8 +313,7 @@
 
         if (context)
         {
-            context->blendEquationRGB = modeRGB;
-            context->blendEquationAlpha = modeAlpha;
+            context->setBlendEquation(modeRGB, modeAlpha);
         }
     }
     catch(std::bad_alloc&)
@@ -440,10 +436,7 @@
 
         if (context)
         {
-            context->sourceBlendRGB = srcRGB;
-            context->sourceBlendAlpha = srcAlpha;
-            context->destBlendRGB = dstRGB;
-            context->destBlendAlpha = dstAlpha;
+            context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
         }
     }
     catch(std::bad_alloc&)
@@ -676,10 +669,7 @@
 
         if (context)
         {
-            context->colorMaskRed = red != GL_FALSE;
-            context->colorMaskGreen = green != GL_FALSE;
-            context->colorMaskBlue = blue != GL_FALSE;
-            context->colorMaskAlpha = alpha != GL_FALSE;
+            context->setColorMask(red != GL_FALSE, green != GL_FALSE, blue != GL_FALSE, alpha != GL_FALSE);
         }
     }
     catch(std::bad_alloc&)
@@ -1028,7 +1018,7 @@
 
                 if (context)
                 {
-                    context->cullMode = mode;
+                    context->setCullMode(mode);
                 }
             }
             break;
@@ -1253,7 +1243,7 @@
 
         if (context)
         {
-            context->depthFunc = func;
+            context->setDepthFunc(func);
         }
     }
     catch(std::bad_alloc&)
@@ -1272,7 +1262,7 @@
 
         if (context)
         {
-            context->depthMask = flag != GL_FALSE;
+            context->setDepthMask(flag != GL_FALSE);
         }
     }
     catch(std::bad_alloc&)
@@ -1291,8 +1281,7 @@
 
         if (context)
         {
-            context->zNear = zNear;
-            context->zFar = zFar;
+            context->setDepthRange(zNear, zFar);
         }
     }
     catch(std::bad_alloc&)
@@ -1366,15 +1355,15 @@
         {
             switch (cap)
             {
-              case GL_CULL_FACE:                context->cullFace = false;              break;
-              case GL_POLYGON_OFFSET_FILL:      context->polygonOffsetFill = false;     break;
-              case GL_SAMPLE_ALPHA_TO_COVERAGE: context->sampleAlphaToCoverage = false; break;
-              case GL_SAMPLE_COVERAGE:          context->sampleCoverage = false;        break;
-              case GL_SCISSOR_TEST:             context->scissorTest = false;           break;
-              case GL_STENCIL_TEST:             context->stencilTest = false;           break;
-              case GL_DEPTH_TEST:               context->depthTest = false;             break;
-              case GL_BLEND:                    context->blend = false;                 break;
-              case GL_DITHER:                   context->dither = false;                break;
+              case GL_CULL_FACE:                context->setCullFace(false);              break;
+              case GL_POLYGON_OFFSET_FILL:      context->setPolygonOffsetFill(false);     break;
+              case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break;
+              case GL_SAMPLE_COVERAGE:          context->setSampleCoverage(false);        break;
+              case GL_SCISSOR_TEST:             context->setScissorTest(false);           break;
+              case GL_STENCIL_TEST:             context->setStencilTest(false);           break;
+              case GL_DEPTH_TEST:               context->setDepthTest(false);             break;
+              case GL_BLEND:                    context->setBlend(false);                 break;
+              case GL_DITHER:                   context->setDither(false);                break;
               default:
                 return error(GL_INVALID_ENUM);
             }
@@ -1401,7 +1390,7 @@
 
         if (context)
         {
-            context->vertexAttribute[index].mEnabled = false;
+            context->setVertexAttribEnabled(index, false);
         }
     }
     catch(std::bad_alloc&)
@@ -1480,15 +1469,15 @@
         {
             switch (cap)
             {
-              case GL_CULL_FACE:                context->cullFace = true;              break;
-              case GL_POLYGON_OFFSET_FILL:      context->polygonOffsetFill = true;     break;
-              case GL_SAMPLE_ALPHA_TO_COVERAGE: context->sampleAlphaToCoverage = true; break;
-              case GL_SAMPLE_COVERAGE:          context->sampleCoverage = true;        break;
-              case GL_SCISSOR_TEST:             context->scissorTest = true;           break;
-              case GL_STENCIL_TEST:             context->stencilTest = true;           break;
-              case GL_DEPTH_TEST:               context->depthTest = true;             break;
-              case GL_BLEND:                    context->blend = true;                 break;
-              case GL_DITHER:                   context->dither = true;                break;
+              case GL_CULL_FACE:                context->setCullFace(true);              break;
+              case GL_POLYGON_OFFSET_FILL:      context->setPolygonOffsetFill(true);     break;
+              case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(true); break;
+              case GL_SAMPLE_COVERAGE:          context->setSampleCoverage(true);        break;
+              case GL_SCISSOR_TEST:             context->setScissorTest(true);           break;
+              case GL_STENCIL_TEST:             context->setStencilTest(true);           break;
+              case GL_DEPTH_TEST:               context->setDepthTest(true);             break;
+              case GL_BLEND:                    context->setBlend(true);                 break;
+              case GL_DITHER:                   context->setDither(true);                break;
               default:
                 return error(GL_INVALID_ENUM);
             }
@@ -1515,7 +1504,7 @@
 
         if (context)
         {
-            context->vertexAttribute[index].mEnabled = true;
+            context->setVertexAttribEnabled(index, true);
         }
     }
     catch(std::bad_alloc&)
@@ -1580,7 +1569,7 @@
         {
             gl::Framebuffer *framebuffer = context->getFramebuffer();
 
-            if (context->framebuffer == 0 || !framebuffer)
+            if (context->getFramebufferHandle() == 0 || !framebuffer)
             {
                 return error(GL_INVALID_OPERATION);
             }
@@ -1679,7 +1668,7 @@
 
             gl::Framebuffer *framebuffer = context->getFramebuffer();
 
-            if (context->framebuffer == 0 || !framebuffer)
+            if (context->getFramebufferHandle() == 0 || !framebuffer)
             {
                 return error(GL_INVALID_OPERATION);
             }
@@ -1713,7 +1702,7 @@
 
                 if (context)
                 {
-                    context->frontFace = mode;
+                    context->setFrontFace(mode);
                 }
             }
             break;
@@ -2235,7 +2224,7 @@
 
         if (context)
         {
-            if (context->framebuffer == 0)
+            if (context->getFramebufferHandle() == 0)
             {
                 return error(GL_INVALID_OPERATION);
             }
@@ -2497,12 +2486,12 @@
                 return error(GL_INVALID_ENUM);
             }
 
-            if (context->renderbuffer == 0)
+            if (context->getRenderbufferHandle() == 0)
             {
                 return error(GL_INVALID_OPERATION);
             }
 
-            gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->renderbuffer);
+            gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle());
 
             switch (pname)
             {
@@ -3001,30 +2990,32 @@
                 return error(GL_INVALID_VALUE);
             }
 
+            gl::AttributeState attribState = context->getVertexAttribState(index);
+
             switch (pname)
             {
               case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
-                *params = (GLfloat)(context->vertexAttribute[index].mEnabled ? GL_TRUE : GL_FALSE);
+                *params = (GLfloat)(attribState.mEnabled ? GL_TRUE : GL_FALSE);
                 break;
               case GL_VERTEX_ATTRIB_ARRAY_SIZE:
-                *params = (GLfloat)context->vertexAttribute[index].mSize;
+                *params = (GLfloat)attribState.mSize;
                 break;
               case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
-                *params = (GLfloat)context->vertexAttribute[index].mStride;
+                *params = (GLfloat)attribState.mStride;
                 break;
               case GL_VERTEX_ATTRIB_ARRAY_TYPE:
-                *params = (GLfloat)context->vertexAttribute[index].mType;
+                *params = (GLfloat)attribState.mType;
                 break;
               case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
-                *params = (GLfloat)(context->vertexAttribute[index].mNormalized ? GL_TRUE : GL_FALSE);
+                *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
                 break;
               case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
-                *params = (GLfloat)context->vertexAttribute[index].mBoundBuffer;
+                *params = (GLfloat)attribState.mBoundBuffer;
                 break;
               case GL_CURRENT_VERTEX_ATTRIB:
                 for (int i = 0; i < 4; ++i)
                 {
-                    params[i] = context->vertexAttribute[index].mCurrentValue[i];
+                    params[i] = attribState.mCurrentValue[i];
                 }
                 break;
               default: return error(GL_INVALID_ENUM);
@@ -3052,30 +3043,32 @@
                 return error(GL_INVALID_VALUE);
             }
 
+            gl::AttributeState attribState = context->getVertexAttribState(index);
+
             switch (pname)
             {
               case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
-                *params = (context->vertexAttribute[index].mEnabled ? GL_TRUE : GL_FALSE);
+                *params = (attribState.mEnabled ? GL_TRUE : GL_FALSE);
                 break;
               case GL_VERTEX_ATTRIB_ARRAY_SIZE:
-                *params = context->vertexAttribute[index].mSize;
+                *params = attribState.mSize;
                 break;
               case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
-                *params = context->vertexAttribute[index].mStride;
+                *params = attribState.mStride;
                 break;
               case GL_VERTEX_ATTRIB_ARRAY_TYPE:
-                *params = context->vertexAttribute[index].mType;
+                *params = attribState.mType;
                 break;
               case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
-                *params = (context->vertexAttribute[index].mNormalized ? GL_TRUE : GL_FALSE);
+                *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
                 break;
               case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
-                *params = context->vertexAttribute[index].mBoundBuffer;
+                *params = attribState.mBoundBuffer;
                 break;
               case GL_CURRENT_VERTEX_ATTRIB:
                 for (int i = 0; i < 4; ++i)
                 {
-                    float currentValue = context->vertexAttribute[index].mCurrentValue[i];
+                    float currentValue = attribState.mCurrentValue[i];
                     params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
                 }
                 break;
@@ -3109,7 +3102,7 @@
                 return error(GL_INVALID_ENUM);
             }
 
-            *pointer = const_cast<GLvoid*>(context->vertexAttribute[index].mPointer);
+            *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
         }
     }
     catch(std::bad_alloc&)
@@ -3145,7 +3138,7 @@
         if (context)
         {
             if (target == GL_GENERATE_MIPMAP_HINT)
-                context->generateMipmapHint = mode;
+                context->setGenerateMipmapHint(mode);
         }
     }
     catch(std::bad_alloc&)
@@ -3192,15 +3185,15 @@
         {
             switch (cap)
             {
-              case GL_CULL_FACE:                return context->cullFace;
-              case GL_POLYGON_OFFSET_FILL:      return context->polygonOffsetFill;
-              case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->sampleAlphaToCoverage;
-              case GL_SAMPLE_COVERAGE:          return context->sampleCoverage;
-              case GL_SCISSOR_TEST:             return context->scissorTest;
-              case GL_STENCIL_TEST:             return context->stencilTest;
-              case GL_DEPTH_TEST:               return context->depthTest;
-              case GL_BLEND:                    return context->blend;
-              case GL_DITHER:                   return context->dither;
+              case GL_CULL_FACE:                return context->isCullFaceEnabled();
+              case GL_POLYGON_OFFSET_FILL:      return context->isPolygonOffsetFillEnabled();
+              case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
+              case GL_SAMPLE_COVERAGE:          return context->isSampleCoverageEnabled();
+              case GL_SCISSOR_TEST:             return context->isScissorTestEnabled();
+              case GL_STENCIL_TEST:             return context->isStencilTestEnabled();
+              case GL_DEPTH_TEST:               return context->isDepthTestEnabled();
+              case GL_BLEND:                    return context->isBlendEnabled();
+              case GL_DITHER:                   return context->isDitherEnabled();
               default:
                 return error(GL_INVALID_ENUM, false);
             }
@@ -3359,7 +3352,7 @@
 
         if (context)
         {
-            context->lineWidth = width;
+            context->setLineWidth(width);
         }
     }
     catch(std::bad_alloc&)
@@ -3419,7 +3412,7 @@
                     return error(GL_INVALID_VALUE);
                 }
 
-                context->unpackAlignment = param;
+                context->setUnpackAlignment(param);
                 break;
 
               case GL_PACK_ALIGNMENT:
@@ -3428,7 +3421,7 @@
                     return error(GL_INVALID_VALUE);
                 }
 
-                context->packAlignment = param;
+                context->setPackAlignment(param);
                 break;
 
               default:
@@ -3452,8 +3445,7 @@
 
         if (context)
         {
-            context->polygonOffsetFactor = factor;
-            context->polygonOffsetUnits = units;
+            context->setPolygonOffsetParams(factor, units);
         }
     }
     catch(std::bad_alloc&)
@@ -3562,7 +3554,7 @@
 
         if (context)
         {
-            if (context->framebuffer == 0 || context->renderbuffer == 0)
+            if (context->getFramebufferHandle() == 0 || context->getRenderbufferHandle() == 0)
             {
                 return error(GL_INVALID_OPERATION);
             }
@@ -3601,8 +3593,7 @@
 
         if (context)
         {
-            context->sampleCoverageValue = gl::clamp01(value);
-            context->sampleCoverageInvert = invert;
+            context->setSampleCoverageParams(gl::clamp01(value), invert);
         }
     }
     catch(std::bad_alloc&)
@@ -3626,10 +3617,7 @@
 
         if (context)
         {
-            context->scissorX = x;
-            context->scissorY = y;
-            context->scissorWidth = width;
-            context->scissorHeight = height;
+            context->setScissorParams(x, y, width, height);
         }
     }
     catch(std::bad_alloc&)
@@ -3736,16 +3724,12 @@
         {
             if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
             {
-                context->stencilFunc = func;
-                context->stencilRef = ref;
-                context->stencilMask = mask;
+                context->setStencilParams(func, ref, mask);
             }
 
             if (face == GL_BACK || face == GL_FRONT_AND_BACK)
             {
-                context->stencilBackFunc = func;
-                context->stencilBackRef = ref;
-                context->stencilBackMask = mask;
+                context->setStencilBackParams(func, ref, mask);
             }
         }
     }
@@ -3782,12 +3766,12 @@
         {
             if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
             {
-                context->stencilWritemask = mask;
+                context->setStencilWritemask(mask);
             }
 
             if (face == GL_BACK || face == GL_FRONT_AND_BACK)
             {
-                context->stencilBackWritemask = mask;
+                context->setStencilBackWritemask(mask);
             }
         }
     }
@@ -3870,16 +3854,12 @@
         {
             if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
             {
-                context->stencilFail = fail;
-                context->stencilPassDepthFail = zfail;
-                context->stencilPassDepthPass = zpass;
+                context->setStencilOperations(fail, zfail, zpass);
             }
 
             if (face == GL_BACK || face == GL_FRONT_AND_BACK)
             {
-                context->stencilBackFail = fail;
-                context->stencilBackPassDepthFail = zfail;
-                context->stencilBackPassDepthPass = zpass;
+                context->setStencilBackOperations(fail, zfail, zpass);
             }
         }
     }
@@ -3997,7 +3977,7 @@
                     return error(GL_INVALID_OPERATION);
                 }
 
-                texture->setImage(level, internalformat, width, height, format, type, context->unpackAlignment, pixels);
+                texture->setImage(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
             }
             else
             {
@@ -4011,22 +3991,22 @@
                 switch (target)
                 {
                   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-                    texture->setImagePosX(level, internalformat, width, height, format, type, context->unpackAlignment, pixels);
+                    texture->setImagePosX(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
                     break;
                   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-                    texture->setImageNegX(level, internalformat, width, height, format, type, context->unpackAlignment, pixels);
+                    texture->setImageNegX(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
                     break;
                   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-                    texture->setImagePosY(level, internalformat, width, height, format, type, context->unpackAlignment, pixels);
+                    texture->setImagePosY(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
                     break;
                   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-                    texture->setImageNegY(level, internalformat, width, height, format, type, context->unpackAlignment, pixels);
+                    texture->setImageNegY(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
                     break;
                   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-                    texture->setImagePosZ(level, internalformat, width, height, format, type, context->unpackAlignment, pixels);
+                    texture->setImagePosZ(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
                     break;
                   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-                    texture->setImageNegZ(level, internalformat, width, height, format, type, context->unpackAlignment, pixels);
+                    texture->setImageNegZ(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
                     break;
                   default: UNREACHABLE();
                 }
@@ -4163,7 +4143,7 @@
                     return error(GL_INVALID_OPERATION);
                 }
 
-                texture->subImage(level, xoffset, yoffset, width, height, format, type, context->unpackAlignment, pixels);
+                texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
             }
             else if (gl::IsCubemapTextureTarget(target))
             {
@@ -4174,7 +4154,7 @@
                     return error(GL_INVALID_OPERATION);
                 }
 
-                texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->unpackAlignment, pixels);
+                texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
             }
             else
             {
@@ -4982,12 +4962,7 @@
 
         if (context)
         {
-            context->vertexAttribute[index].mBoundBuffer = context->arrayBuffer;
-            context->vertexAttribute[index].mSize = size;
-            context->vertexAttribute[index].mType = type;
-            context->vertexAttribute[index].mNormalized = (normalized == GL_TRUE);
-            context->vertexAttribute[index].mStride = stride;
-            context->vertexAttribute[index].mPointer = ptr;
+            context->setVertexAttribState(index, context->getArrayBufferHandle(), size, type, (normalized == GL_TRUE), stride, ptr);
         }
     }
     catch(std::bad_alloc&)
@@ -5011,10 +4986,7 @@
 
         if (context)
         {
-            context->viewportX = x;
-            context->viewportY = y;
-            context->viewportWidth = width;
-            context->viewportHeight = height;
+            context->setViewportParams(x, y, width, height);
         }
     }
     catch(std::bad_alloc&)