Proliferate gl::Context everywhere.

This gives the D3D back-end access to the GL state almost anywhere.
This uses the onDestroy hook for Textures to push errors up from
destructors, although they still don't quite make it to the Context.

There are places, such as in EGL object (Context/Surface) destruction,
where we end up calling through to GL implementation internals without
having access to a gl::Context. We handle this via a proxy Context
to a Display, basically a null context, that has access to impl-side
state like the Renderer pointer if necessary. It does not have access
to the normal GL state.

Also Pass gl::Context to RefCountObject::release(). Since we're using
destroy() methods now, we should not ever call the destructor directly.

BUG=angleproject:1156

Change-Id: Ie4c32ad6bf6caaff0289901f30b5c6bafa2ce259
Reviewed-on: https://chromium-review.googlesource.com/529707
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/common/angleutils.h b/src/common/angleutils.h
index d446411..61da3df 100644
--- a/src/common/angleutils.h
+++ b/src/common/angleutils.h
@@ -45,6 +45,7 @@
 class UniqueObjectPointer : angle::NonCopyable
 {
   public:
+    UniqueObjectPointer(const ContextT *context) : mObject(nullptr), mContext(context) {}
     UniqueObjectPointer(ObjT *obj, const ContextT *context) : mObject(obj), mContext(context) {}
     ~UniqueObjectPointer()
     {
@@ -63,6 +64,17 @@
         return obj;
     }
 
+    ObjT *get() const { return mObject; }
+
+    void reset(ObjT *obj)
+    {
+        if (mObject)
+        {
+            mObject->onDestroy(mContext);
+        }
+        mObject = obj;
+    }
+
   private:
     ObjT *mObject;
     const ContextT *mContext;
diff --git a/src/libANGLE/Buffer.cpp b/src/libANGLE/Buffer.cpp
index 77b9ff9..829d3d5 100644
--- a/src/libANGLE/Buffer.cpp
+++ b/src/libANGLE/Buffer.cpp
@@ -44,7 +44,7 @@
     SafeDelete(mImpl);
 }
 
-void Buffer::destroy(const Context *context)
+void Buffer::onDestroy(const Context *context)
 {
     // In tests, mImpl might be null.
     if (mImpl)
diff --git a/src/libANGLE/Buffer.h b/src/libANGLE/Buffer.h
index f13f45d..cc3522d 100644
--- a/src/libANGLE/Buffer.h
+++ b/src/libANGLE/Buffer.h
@@ -65,7 +65,7 @@
   public:
     Buffer(rx::GLImplFactory *factory, GLuint id);
     ~Buffer() override;
-    void destroy(const Context *context) override;
+    void onDestroy(const Context *context) override;
 
     void setLabel(const std::string &label) override;
     const std::string &getLabel() const override;
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index ec4de3e..94f3e12 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -129,7 +129,7 @@
         for (size_t tfBufferIndex = 0; tfBufferIndex < transformFeedback->getIndexedBufferCount();
              tfBufferIndex++)
         {
-            const OffsetBindingPointer<gl::Buffer> &buffer =
+            const gl::OffsetBindingPointer<gl::Buffer> &buffer =
                 transformFeedback->getIndexedBuffer(tfBufferIndex);
             if (buffer.get() != nullptr)
             {
@@ -280,9 +280,8 @@
     initCaps(displayExtensions);
     initWorkarounds();
 
-    mGLState.initialize(mCaps, mExtensions, getClientVersion(), GetDebug(attribs),
-                        GetBindGeneratesResource(attribs), GetClientArraysEnabled(attribs),
-                        robustResourceInit);
+    mGLState.initialize(this, GetDebug(attribs), GetBindGeneratesResource(attribs),
+                        GetClientArraysEnabled(attribs), robustResourceInit);
 
     mFenceNVHandleAllocator.setBaseHandle(0);
 
@@ -293,25 +292,25 @@
     // objects all of whose names are 0.
 
     Texture *zeroTexture2D = new Texture(mImplementation.get(), 0, GL_TEXTURE_2D);
-    mZeroTextures[GL_TEXTURE_2D].set(zeroTexture2D);
+    mZeroTextures[GL_TEXTURE_2D].set(this, zeroTexture2D);
 
     Texture *zeroTextureCube = new Texture(mImplementation.get(), 0, GL_TEXTURE_CUBE_MAP);
-    mZeroTextures[GL_TEXTURE_CUBE_MAP].set(zeroTextureCube);
+    mZeroTextures[GL_TEXTURE_CUBE_MAP].set(this, zeroTextureCube);
 
     if (getClientVersion() >= Version(3, 0))
     {
         // TODO: These could also be enabled via extension
         Texture *zeroTexture3D = new Texture(mImplementation.get(), 0, GL_TEXTURE_3D);
-        mZeroTextures[GL_TEXTURE_3D].set(zeroTexture3D);
+        mZeroTextures[GL_TEXTURE_3D].set(this, zeroTexture3D);
 
         Texture *zeroTexture2DArray = new Texture(mImplementation.get(), 0, GL_TEXTURE_2D_ARRAY);
-        mZeroTextures[GL_TEXTURE_2D_ARRAY].set(zeroTexture2DArray);
+        mZeroTextures[GL_TEXTURE_2D_ARRAY].set(this, zeroTexture2DArray);
     }
     if (getClientVersion() >= Version(3, 1))
     {
         Texture *zeroTexture2DMultisample =
             new Texture(mImplementation.get(), 0, GL_TEXTURE_2D_MULTISAMPLE);
-        mZeroTextures[GL_TEXTURE_2D_MULTISAMPLE].set(zeroTexture2DMultisample);
+        mZeroTextures[GL_TEXTURE_2D_MULTISAMPLE].set(this, zeroTexture2DMultisample);
 
         bindGenericAtomicCounterBuffer(0);
         for (unsigned int i = 0; i < mCaps.maxAtomicCounterBufferBindings; i++)
@@ -330,10 +329,10 @@
     {
         Texture *zeroTextureExternal =
             new Texture(mImplementation.get(), 0, GL_TEXTURE_EXTERNAL_OES);
-        mZeroTextures[GL_TEXTURE_EXTERNAL_OES].set(zeroTextureExternal);
+        mZeroTextures[GL_TEXTURE_EXTERNAL_OES].set(this, zeroTextureExternal);
     }
 
-    mGLState.initializeZeroTextures(mZeroTextures);
+    mGLState.initializeZeroTextures(this, mZeroTextures);
 
     bindVertexArray(0);
     bindArrayBuffer(0);
@@ -404,10 +403,8 @@
     handleError(mImplementation->initialize());
 }
 
-void Context::destroy(egl::Display *display)
+egl::Error Context::onDestroy(const egl::Display *display)
 {
-    mGLState.reset(this);
-
     for (auto fence : mFenceNVMap)
     {
         SafeDelete(fence.second);
@@ -417,13 +414,16 @@
     {
         if (query.second != nullptr)
         {
-            query.second->release();
+            query.second->release(this);
         }
     }
 
     for (auto vertexArray : mVertexArrayMap)
     {
-        SafeDelete(vertexArray.second);
+        if (vertexArray.second)
+        {
+            vertexArray.second->onDestroy(this);
+        }
     }
 
     for (auto transformFeedback : mTransformFeedbackMap)
@@ -436,15 +436,18 @@
 
     for (auto &zeroTexture : mZeroTextures)
     {
-        zeroTexture.second.set(nullptr);
+        zeroTexture.second->onDestroy(this);
+        zeroTexture.second.set(this, nullptr);
     }
     mZeroTextures.clear();
 
     SafeDelete(mSurfacelessFramebuffer);
 
-    releaseSurface(display);
+    ANGLE_TRY(releaseSurface(display));
     releaseShaderCompiler();
 
+    mGLState.reset(this);
+
     mState.mBuffers->release(this);
     mState.mShaderPrograms->release(this);
     mState.mTextures->release(this);
@@ -453,13 +456,15 @@
     mState.mFenceSyncs->release(this);
     mState.mPaths->release(this);
     mState.mFramebuffers->release(this);
+
+    return egl::NoError();
 }
 
 Context::~Context()
 {
 }
 
-void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
+egl::Error Context::makeCurrent(egl::Display *display, egl::Surface *surface)
 {
     mCurrentDisplay = display;
 
@@ -486,12 +491,12 @@
     // TODO(jmadill): Rework this when we support ContextImpl
     mGLState.setAllDirtyBits();
 
-    releaseSurface(display);
+    ANGLE_TRY(releaseSurface(display));
 
     Framebuffer *newDefault = nullptr;
     if (surface != nullptr)
     {
-        surface->setIsCurrent(display, true);
+        ANGLE_TRY(surface->setIsCurrent(this, true));
         mCurrentSurface = surface;
         newDefault      = surface->getDefaultFramebuffer();
     }
@@ -520,10 +525,11 @@
     }
 
     // Notify the renderer of a context switch
-    mImplementation->onMakeCurrent(mState);
+    mImplementation->onMakeCurrent(this);
+    return egl::NoError();
 }
 
-void Context::releaseSurface(egl::Display *display)
+egl::Error Context::releaseSurface(const egl::Display *display)
 {
     // Remove the default framebuffer
     Framebuffer *currentDefault = nullptr;
@@ -548,9 +554,11 @@
 
     if (mCurrentSurface)
     {
-        mCurrentSurface->setIsCurrent(display, false);
+        ANGLE_TRY(mCurrentSurface->setIsCurrent(this, false));
         mCurrentSurface = nullptr;
     }
+
+    return egl::NoError();
 }
 
 GLuint Context::createBuffer()
@@ -789,7 +797,7 @@
         if (vertexArrayObject != nullptr)
         {
             detachVertexArray(vertexArray);
-            delete vertexArrayObject;
+            vertexArrayObject->onDestroy(this);
         }
 
         mVertexArrayMap.erase(iter);
@@ -859,7 +867,7 @@
         mQueryHandleAllocator.release(queryObject->first);
         if (queryObject->second)
         {
-            queryObject->second->release();
+            queryObject->second->release(this);
         }
         mQueryMap.erase(queryObject);
     }
@@ -989,19 +997,19 @@
 void Context::bindArrayBuffer(GLuint bufferHandle)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setArrayBufferBinding(buffer);
+    mGLState.setArrayBufferBinding(this, buffer);
 }
 
 void Context::bindDrawIndirectBuffer(GLuint bufferHandle)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setDrawIndirectBufferBinding(buffer);
+    mGLState.setDrawIndirectBufferBinding(this, buffer);
 }
 
 void Context::bindElementArrayBuffer(GLuint bufferHandle)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setElementArrayBuffer(buffer);
+    mGLState.setElementArrayBuffer(this, buffer);
 }
 
 void Context::bindTexture(GLenum target, GLuint handle)
@@ -1018,7 +1026,7 @@
     }
 
     ASSERT(texture);
-    mGLState.setSamplerTexture(target, texture);
+    mGLState.setSamplerTexture(this, target, texture);
 }
 
 void Context::bindReadFramebuffer(GLuint framebufferHandle)
@@ -1047,7 +1055,7 @@
                                GLsizei stride)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.bindVertexBuffer(bindingIndex, buffer, offset, stride);
+    mGLState.bindVertexBuffer(this, bindingIndex, buffer, offset, stride);
 }
 
 void Context::bindSampler(GLuint textureUnit, GLuint samplerHandle)
@@ -1055,13 +1063,13 @@
     ASSERT(textureUnit < mCaps.maxCombinedTextureImageUnits);
     Sampler *sampler =
         mState.mSamplers->checkSamplerAllocation(mImplementation.get(), samplerHandle);
-    mGLState.setSamplerBinding(textureUnit, sampler);
+    mGLState.setSamplerBinding(this, textureUnit, sampler);
 }
 
 void Context::bindGenericUniformBuffer(GLuint bufferHandle)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setGenericUniformBufferBinding(buffer);
+    mGLState.setGenericUniformBufferBinding(this, buffer);
 }
 
 void Context::bindIndexedUniformBuffer(GLuint bufferHandle,
@@ -1070,13 +1078,13 @@
                                        GLsizeiptr size)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setIndexedUniformBufferBinding(index, buffer, offset, size);
+    mGLState.setIndexedUniformBufferBinding(this, index, buffer, offset, size);
 }
 
 void Context::bindGenericTransformFeedbackBuffer(GLuint bufferHandle)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.getCurrentTransformFeedback()->bindGenericBuffer(buffer);
+    mGLState.getCurrentTransformFeedback()->bindGenericBuffer(this, buffer);
 }
 
 void Context::bindIndexedTransformFeedbackBuffer(GLuint bufferHandle,
@@ -1085,13 +1093,13 @@
                                                  GLsizeiptr size)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.getCurrentTransformFeedback()->bindIndexedBuffer(index, buffer, offset, size);
+    mGLState.getCurrentTransformFeedback()->bindIndexedBuffer(this, index, buffer, offset, size);
 }
 
 void Context::bindGenericAtomicCounterBuffer(GLuint bufferHandle)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setGenericAtomicCounterBufferBinding(buffer);
+    mGLState.setGenericAtomicCounterBufferBinding(this, buffer);
 }
 
 void Context::bindIndexedAtomicCounterBuffer(GLuint bufferHandle,
@@ -1100,13 +1108,13 @@
                                              GLsizeiptr size)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setIndexedAtomicCounterBufferBinding(index, buffer, offset, size);
+    mGLState.setIndexedAtomicCounterBufferBinding(this, index, buffer, offset, size);
 }
 
 void Context::bindGenericShaderStorageBuffer(GLuint bufferHandle)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setGenericShaderStorageBufferBinding(buffer);
+    mGLState.setGenericShaderStorageBufferBinding(this, buffer);
 }
 
 void Context::bindIndexedShaderStorageBuffer(GLuint bufferHandle,
@@ -1115,31 +1123,31 @@
                                              GLsizeiptr size)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setIndexedShaderStorageBufferBinding(index, buffer, offset, size);
+    mGLState.setIndexedShaderStorageBufferBinding(this, index, buffer, offset, size);
 }
 
 void Context::bindCopyReadBuffer(GLuint bufferHandle)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setCopyReadBufferBinding(buffer);
+    mGLState.setCopyReadBufferBinding(this, buffer);
 }
 
 void Context::bindCopyWriteBuffer(GLuint bufferHandle)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setCopyWriteBufferBinding(buffer);
+    mGLState.setCopyWriteBufferBinding(this, buffer);
 }
 
 void Context::bindPixelPackBuffer(GLuint bufferHandle)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setPixelPackBufferBinding(buffer);
+    mGLState.setPixelPackBufferBinding(this, buffer);
 }
 
 void Context::bindPixelUnpackBuffer(GLuint bufferHandle)
 {
     Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
-    mGLState.setPixelUnpackBufferBinding(buffer);
+    mGLState.setPixelUnpackBufferBinding(this, buffer);
 }
 
 void Context::useProgram(GLuint program)
@@ -1151,7 +1159,7 @@
 {
     TransformFeedback *transformFeedback =
         checkTransformFeedbackAllocation(transformFeedbackHandle);
-    mGLState.setTransformFeedbackBinding(transformFeedback);
+    mGLState.setTransformFeedbackBinding(this, transformFeedback);
 }
 
 Error Context::beginQuery(GLenum target, GLuint query)
@@ -1167,7 +1175,7 @@
     }
 
     // set query as active for specified target only if begin succeeded
-    mGLState.setActiveQuery(target, queryObject);
+    mGLState.setActiveQuery(this, target, queryObject);
 
     return NoError();
 }
@@ -1180,7 +1188,7 @@
     gl::Error error = queryObject->end();
 
     // Always unbind the query, even if there was an error. This may delete the query object.
-    mGLState.setActiveQuery(target, nullptr);
+    mGLState.setActiveQuery(this, target, nullptr);
 
     return error;
 }
@@ -1302,7 +1310,7 @@
 {
     if (mCompiler.get() == nullptr)
     {
-        mCompiler.set(new Compiler(mImplementation.get(), mState));
+        mCompiler.set(this, new Compiler(mImplementation.get(), mState));
     }
     return mCompiler.get();
 }
@@ -1801,25 +1809,25 @@
 void Context::texParameterf(GLenum target, GLenum pname, GLfloat param)
 {
     Texture *texture = getTargetTexture(target);
-    SetTexParameterf(texture, pname, param);
+    SetTexParameterf(this, texture, pname, param);
 }
 
 void Context::texParameterfv(GLenum target, GLenum pname, const GLfloat *params)
 {
     Texture *texture = getTargetTexture(target);
-    SetTexParameterfv(texture, pname, params);
+    SetTexParameterfv(this, texture, pname, params);
 }
 
 void Context::texParameteri(GLenum target, GLenum pname, GLint param)
 {
     Texture *texture = getTargetTexture(target);
-    SetTexParameteri(texture, pname, param);
+    SetTexParameteri(this, texture, pname, param);
 }
 
 void Context::texParameteriv(GLenum target, GLenum pname, const GLint *params)
 {
     Texture *texture = getTargetTexture(target);
-    SetTexParameteriv(texture, pname, params);
+    SetTexParameteriv(this, texture, pname, params);
 }
 
 void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
@@ -2341,7 +2349,7 @@
     // Attachments to unbound container objects, such as
     // deletion of a buffer attached to a vertex array object which is not bound to the context,
     // are not affected and continue to act as references on the deleted object
-    mGLState.detachBuffer(buffer);
+    mGLState.detachBuffer(this, buffer);
 }
 
 void Context::detachFramebuffer(GLuint framebuffer)
@@ -2395,7 +2403,7 @@
     // The OpenGL specification doesn't mention what should happen when the currently bound
     // transform feedback object is deleted. Since it is a container object, we treat it like
     // VAOs and FBOs and set the current bound transform feedback back to 0.
-    if (mGLState.removeTransformFeedbackBinding(transformFeedback))
+    if (mGLState.removeTransformFeedbackBinding(this, transformFeedback))
     {
         bindTransformFeedback(0);
     }
@@ -2403,7 +2411,7 @@
 
 void Context::detachSampler(GLuint sampler)
 {
-    mGLState.detachSampler(sampler);
+    mGLState.detachSampler(this, sampler);
 }
 
 void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
@@ -3091,7 +3099,7 @@
 
     // The specification isn't clear what should be done when the framebuffer isn't complete.
     // We leave it up to the framebuffer implementation to decide what to do.
-    handleError(framebuffer->discard(numAttachments, attachments));
+    handleError(framebuffer->discard(this, numAttachments, attachments));
 }
 
 void Context::invalidateFramebuffer(GLenum target,
@@ -3109,7 +3117,7 @@
         return;
     }
 
-    handleError(framebuffer->invalidate(numAttachments, attachments));
+    handleError(framebuffer->invalidate(this, numAttachments, attachments));
 }
 
 void Context::invalidateSubFramebuffer(GLenum target,
@@ -3132,7 +3140,7 @@
     }
 
     Rectangle area(x, y, width, height);
-    handleError(framebuffer->invalidateSub(numAttachments, attachments, area));
+    handleError(framebuffer->invalidateSub(this, numAttachments, attachments, area));
 }
 
 void Context::texImage2D(GLenum target,
@@ -3743,8 +3751,8 @@
                                   GLsizei stride,
                                   const void *ptr)
 {
-    mGLState.setVertexAttribState(index, mGLState.getTargetBuffer(GL_ARRAY_BUFFER), size, type,
-                                  normalized == GL_TRUE, false, stride, ptr);
+    mGLState.setVertexAttribState(this, index, mGLState.getTargetBuffer(GL_ARRAY_BUFFER), size,
+                                  type, normalized == GL_TRUE, false, stride, ptr);
 }
 
 void Context::vertexAttribFormat(GLuint attribIndex,
@@ -3786,8 +3794,8 @@
                                    GLsizei stride,
                                    const void *pointer)
 {
-    mGLState.setVertexAttribState(index, mGLState.getTargetBuffer(GL_ARRAY_BUFFER), size, type,
-                                  false, true, stride, pointer);
+    mGLState.setVertexAttribState(this, index, mGLState.getTargetBuffer(GL_ARRAY_BUFFER), size,
+                                  type, false, true, stride, pointer);
 }
 
 void Context::vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
@@ -4069,7 +4077,7 @@
     ASSERT(target == GL_RENDERBUFFER);
     Renderbuffer *object =
         mState.mRenderbuffers->checkRenderbufferAllocation(mImplementation.get(), renderbuffer);
-    mGLState.setRenderbufferBinding(object);
+    mGLState.setRenderbufferBinding(this, object);
 }
 
 void Context::texStorage2DMultisample(GLenum target,
@@ -4109,7 +4117,7 @@
     GLenum convertedInternalFormat = getConvertedRenderbufferFormat(internalformat);
 
     Renderbuffer *renderbuffer = mGLState.getCurrentRenderbuffer();
-    handleError(renderbuffer->setStorage(convertedInternalFormat, width, height));
+    handleError(renderbuffer->setStorage(this, convertedInternalFormat, width, height));
 }
 
 void Context::renderbufferStorageMultisample(GLenum target,
@@ -4123,7 +4131,7 @@
 
     Renderbuffer *renderbuffer = mGLState.getCurrentRenderbuffer();
     handleError(
-        renderbuffer->setStorageMultisample(samples, convertedInternalFormat, width, height));
+        renderbuffer->setStorageMultisample(this, samples, convertedInternalFormat, width, height));
 }
 
 void Context::getSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
@@ -4576,7 +4584,7 @@
 
 void Context::releaseShaderCompiler()
 {
-    mCompiler.set(nullptr);
+    mCompiler.set(this, nullptr);
 }
 
 void Context::shaderBinary(GLsizei n,
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index 136438b..01baf70 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -37,6 +37,7 @@
 class AttributeMap;
 class Surface;
 struct Config;
+class Thread;
 }
 
 namespace gl
@@ -67,11 +68,11 @@
             const egl::DisplayExtensions &displayExtensions,
             bool robustResourceInit);
 
-    void destroy(egl::Display *display);
+    egl::Error onDestroy(const egl::Display *display);
     ~Context() override;
 
-    void makeCurrent(egl::Display *display, egl::Surface *surface);
-    void releaseSurface(egl::Display *display);
+    egl::Error makeCurrent(egl::Display *display, egl::Surface *surface);
+    egl::Error releaseSurface(const egl::Display *display);
 
     // These create  and destroy methods are merely pass-throughs to
     // ResourceManager, which owns these object types
diff --git a/src/libANGLE/Display.cpp b/src/libANGLE/Display.cpp
index b60685f..3ab2b86 100644
--- a/src/libANGLE/Display.cpp
+++ b/src/libANGLE/Display.cpp
@@ -372,13 +372,15 @@
       mDevice(eglDevice),
       mPlatform(platform),
       mTextureManager(nullptr),
-      mGlobalTextureShareGroupUsers(0)
+      mGlobalTextureShareGroupUsers(0),
+      mProxyContext(this)
 {
 }
 
 Display::~Display()
 {
-    terminate();
+    // TODO(jmadill): When is this called?
+    // terminate();
 
     if (mPlatform == EGL_PLATFORM_ANGLE_ANGLE)
     {
@@ -403,6 +405,8 @@
         UNREACHABLE();
     }
 
+    mProxyContext.reset(nullptr);
+
     SafeDelete(mDevice);
     SafeDelete(mImplementation);
 }
@@ -486,18 +490,25 @@
         ASSERT(mDevice != nullptr);
     }
 
+    mProxyContext.reset(nullptr);
+    gl::Context *proxyContext = new gl::Context(mImplementation, nullptr, nullptr, nullptr,
+                                                egl::AttributeMap(), mDisplayExtensions, false);
+    mProxyContext.reset(proxyContext);
+
     mInitialized = true;
 
     return NoError();
 }
 
-void Display::terminate()
+Error Display::terminate()
 {
-    makeCurrent(nullptr, nullptr, nullptr);
+    ANGLE_TRY(makeCurrent(nullptr, nullptr, nullptr));
+
+    mProxyContext.reset(nullptr);
 
     while (!mContextSet.empty())
     {
-        destroyContext(*mContextSet.begin());
+        ANGLE_TRY(destroyContext(*mContextSet.begin()));
     }
 
     // The global texture manager should be deleted with the last context that uses it.
@@ -515,7 +526,7 @@
 
     while (!mState.surfaceSet.empty())
     {
-        destroySurface(*mState.surfaceSet.begin());
+        ANGLE_TRY(destroySurface(*mState.surfaceSet.begin()));
     }
 
     mConfigSet.clear();
@@ -537,6 +548,8 @@
 
     // TODO(jmadill): Store Platform in Display and deinit here.
     ANGLEResetDisplayPlatform(this);
+
+    return NoError();
 }
 
 std::vector<const Config*> Display::getConfigs(const egl::AttributeMap &attribs) const
@@ -665,7 +678,8 @@
     }
     ASSERT(sibling != nullptr);
 
-    std::unique_ptr<Image> imagePtr(new Image(mImplementation, target, sibling, attribs));
+    angle::UniqueObjectPointer<Image, gl::Context> imagePtr(
+        new Image(mImplementation, target, sibling, attribs), context);
     ANGLE_TRY(imagePtr->initialize());
 
     Image *image = imagePtr.release();
@@ -736,14 +750,16 @@
     return NoError();
 }
 
-Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
+Error Display::makeCurrent(egl::Surface *drawSurface,
+                           egl::Surface *readSurface,
+                           gl::Context *context)
 {
     ANGLE_TRY(mImplementation->makeCurrent(drawSurface, readSurface, context));
 
     if (context != nullptr)
     {
         ASSERT(readSurface == drawSurface);
-        context->makeCurrent(this, drawSurface);
+        ANGLE_TRY(context->makeCurrent(this, drawSurface));
     }
 
     return NoError();
@@ -763,7 +779,7 @@
     return mImplementation->restoreLostDevice(this);
 }
 
-void Display::destroySurface(Surface *surface)
+Error Display::destroySurface(Surface *surface)
 {
     if (surface->getType() == EGL_WINDOW_BIT)
     {
@@ -785,14 +801,15 @@
     }
 
     mState.surfaceSet.erase(surface);
-    surface->onDestroy(this);
+    ANGLE_TRY(surface->onDestroy(this));
+    return NoError();
 }
 
 void Display::destroyImage(egl::Image *image)
 {
     auto iter = mImageSet.find(image);
     ASSERT(iter != mImageSet.end());
-    (*iter)->release();
+    (*iter)->release(mProxyContext.get());
     mImageSet.erase(iter);
 }
 
@@ -802,7 +819,7 @@
     SafeDelete(stream);
 }
 
-void Display::destroyContext(gl::Context *context)
+Error Display::destroyContext(gl::Context *context)
 {
     if (context->usingDisplayTextureShareGroup())
     {
@@ -817,9 +834,10 @@
         mGlobalTextureShareGroupUsers--;
     }
 
-    context->destroy(this);
+    ANGLE_TRY(context->onDestroy(this));
     mContextSet.erase(context);
     SafeDelete(context);
+    return NoError();
 }
 
 bool Display::isDeviceLost() const
diff --git a/src/libANGLE/Display.h b/src/libANGLE/Display.h
index a4e15f6..0beee75 100644
--- a/src/libANGLE/Display.h
+++ b/src/libANGLE/Display.h
@@ -53,7 +53,7 @@
     ~Display();
 
     Error initialize();
-    void terminate();
+    Error terminate();
 
     static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap);
     static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
@@ -96,10 +96,10 @@
 
     Error makeCurrent(Surface *drawSurface, Surface *readSurface, gl::Context *context);
 
-    void destroySurface(Surface *surface);
+    Error destroySurface(Surface *surface);
     void destroyImage(Image *image);
     void destroyStream(Stream *stream);
-    void destroyContext(gl::Context *context);
+    Error destroyContext(gl::Context *context);
 
     bool isInitialized() const;
     bool isValidConfig(const Config *config) const;
@@ -144,6 +144,8 @@
 
     bool isRobustResourceInitEnabled() const;
 
+    const gl::Context *getProxyContext() const { return mProxyContext.get(); }
+
   private:
     Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice);
 
@@ -187,6 +189,10 @@
 
     gl::TextureManager *mTextureManager;
     size_t mGlobalTextureShareGroupUsers;
+
+    // This gl::Context is a simple proxy to the Display for the GL back-end entry points
+    // that need access to implementation-specific data, like a Renderer object.
+    angle::UniqueObjectPointer<gl::Context, Display> mProxyContext;
 };
 
 }  // namespace egl
diff --git a/src/libANGLE/Fence.h b/src/libANGLE/Fence.h
index 3b250a2..8768407 100644
--- a/src/libANGLE/Fence.h
+++ b/src/libANGLE/Fence.h
@@ -54,7 +54,7 @@
     FenceSync(rx::FenceSyncImpl *impl, GLuint id);
     virtual ~FenceSync();
 
-    void destroy(const Context *context) override {}
+    void onDestroy(const Context *context) override {}
 
     void setLabel(const std::string &label) override;
     const std::string &getLabel() const override;
diff --git a/src/libANGLE/Fence_unittest.cpp b/src/libANGLE/Fence_unittest.cpp
index f7fd215..6305f78 100644
--- a/src/libANGLE/Fence_unittest.cpp
+++ b/src/libANGLE/Fence_unittest.cpp
@@ -111,10 +111,7 @@
         mFence->addRef();
     }
 
-    virtual void TearDown()
-    {
-        mFence->release();
-    }
+    virtual void TearDown() { mFence->release(nullptr); }
 
     MockFenceSyncImpl *mImpl;
     gl::FenceSync* mFence;
@@ -127,7 +124,7 @@
 
     gl::FenceSync* fence = new gl::FenceSync(impl, 1);
     fence->addRef();
-    fence->release();
+    fence->release(nullptr);
 
     // Only needed because the mock is leaked if bugs are present,
     // which logs an error, but does not cause the test to fail.
diff --git a/src/libANGLE/Framebuffer.cpp b/src/libANGLE/Framebuffer.cpp
index 42362b0..fa57dfe 100644
--- a/src/libANGLE/Framebuffer.cpp
+++ b/src/libANGLE/Framebuffer.cpp
@@ -437,7 +437,7 @@
     }
 }
 
-Framebuffer::Framebuffer(egl::Surface *surface)
+Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
     : mState(),
       mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
       mId(0),
@@ -448,17 +448,21 @@
     ASSERT(mImpl != nullptr);
     mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
 
-    setAttachmentImpl(GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(), surface);
+    const Context *proxyContext = display->getProxyContext();
+
+    setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(),
+                      surface);
 
     if (surface->getConfig()->depthSize > 0)
     {
-        setAttachmentImpl(GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(), surface);
+        setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH,
+                          gl::ImageIndex::MakeInvalid(), surface);
     }
 
     if (surface->getConfig()->stencilSize > 0)
     {
-        setAttachmentImpl(GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, gl::ImageIndex::MakeInvalid(),
-                          surface);
+        setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL,
+                          gl::ImageIndex::MakeInvalid(), surface);
     }
 }
 
@@ -478,8 +482,18 @@
     SafeDelete(mImpl);
 }
 
-void Framebuffer::destroy(const Context *context)
+void Framebuffer::onDestroy(const Context *context)
 {
+    for (auto &attachment : mState.mColorAttachments)
+    {
+        attachment.detach(context);
+    }
+    mState.mDepthAttachment.detach(context);
+    mState.mStencilAttachment.detach(context);
+    mState.mWebGLDepthAttachment.detach(context);
+    mState.mWebGLStencilAttachment.detach(context);
+    mState.mWebGLDepthStencilAttachment.detach(context);
+
     mImpl->destroy(context);
 }
 
@@ -512,8 +526,8 @@
 {
     for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
     {
-        detachMatchingAttachment(&mState.mColorAttachments[colorIndex], resourceType, resourceId,
-                                 DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
+        detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
+                                 resourceId, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
     }
 
     if (context->isWebGL1())
@@ -532,21 +546,22 @@
     }
     else
     {
-        detachMatchingAttachment(&mState.mDepthAttachment, resourceType, resourceId,
+        detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId,
                                  DIRTY_BIT_DEPTH_ATTACHMENT);
-        detachMatchingAttachment(&mState.mStencilAttachment, resourceType, resourceId,
+        detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId,
                                  DIRTY_BIT_STENCIL_ATTACHMENT);
     }
 }
 
-void Framebuffer::detachMatchingAttachment(FramebufferAttachment *attachment,
+void Framebuffer::detachMatchingAttachment(const Context *context,
+                                           FramebufferAttachment *attachment,
                                            GLenum matchType,
                                            GLuint matchId,
                                            size_t dirtyBit)
 {
     if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
     {
-        attachment->detach();
+        attachment->detach(context);
         mDirtyBits.set(dirtyBit);
     }
 }
@@ -919,19 +934,22 @@
     return GL_FRAMEBUFFER_COMPLETE;
 }
 
-Error Framebuffer::discard(size_t count, const GLenum *attachments)
+Error Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
 {
-    return mImpl->discard(count, attachments);
+    return mImpl->discard(context, count, attachments);
 }
 
-Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
+Error Framebuffer::invalidate(const Context *context, size_t count, const GLenum *attachments)
 {
-    return mImpl->invalidate(count, attachments);
+    return mImpl->invalidate(context, count, attachments);
 }
 
-Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
+Error Framebuffer::invalidateSub(const Context *context,
+                                 size_t count,
+                                 const GLenum *attachments,
+                                 const gl::Rectangle &area)
 {
-    return mImpl->invalidateSub(count, attachments, area);
+    return mImpl->invalidateSub(context, count, attachments, area);
 }
 
 Error Framebuffer::clear(const gl::Context *context, GLbitfield mask)
@@ -997,14 +1015,14 @@
     return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
 }
 
-GLenum Framebuffer::getImplementationColorReadFormat() const
+GLenum Framebuffer::getImplementationColorReadFormat(const Context *context) const
 {
-    return mImpl->getImplementationColorReadFormat();
+    return mImpl->getImplementationColorReadFormat(context);
 }
 
-GLenum Framebuffer::getImplementationColorReadType() const
+GLenum Framebuffer::getImplementationColorReadType(const Context *context) const
 {
-    return mImpl->getImplementationColorReadType();
+    return mImpl->getImplementationColorReadType(context);
 }
 
 Error Framebuffer::readPixels(const gl::Context *context,
@@ -1094,7 +1112,7 @@
     // Context may be null in unit tests.
     if (!context || !context->isWebGL1())
     {
-        setAttachmentImpl(type, binding, textureIndex, resource);
+        setAttachmentImpl(context, type, binding, textureIndex, resource);
         return;
     }
 
@@ -1102,25 +1120,26 @@
     {
         case GL_DEPTH_STENCIL:
         case GL_DEPTH_STENCIL_ATTACHMENT:
-            mState.mWebGLDepthStencilAttachment.attach(type, binding, textureIndex, resource);
+            mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
+                                                       resource);
             break;
         case GL_DEPTH:
         case GL_DEPTH_ATTACHMENT:
-            mState.mWebGLDepthAttachment.attach(type, binding, textureIndex, resource);
+            mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource);
             break;
         case GL_STENCIL:
         case GL_STENCIL_ATTACHMENT:
-            mState.mWebGLStencilAttachment.attach(type, binding, textureIndex, resource);
+            mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource);
             break;
         default:
-            setAttachmentImpl(type, binding, textureIndex, resource);
+            setAttachmentImpl(context, type, binding, textureIndex, resource);
             return;
     }
 
-    commitWebGL1DepthStencilIfConsistent();
+    commitWebGL1DepthStencilIfConsistent(context);
 }
 
-void Framebuffer::commitWebGL1DepthStencilIfConsistent()
+void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context)
 {
     int count = 0;
 
@@ -1156,35 +1175,40 @@
     if (mState.mWebGLDepthAttachment.isAttached())
     {
         const auto &depth = mState.mWebGLDepthAttachment;
-        setAttachmentImpl(depth.type(), GL_DEPTH_ATTACHMENT,
+        setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
                           getImageIndexIfTextureAttachment(depth), depth.getResource());
-        setAttachmentImpl(GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
+        setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
+                          nullptr);
     }
     else if (mState.mWebGLStencilAttachment.isAttached())
     {
         const auto &stencil = mState.mWebGLStencilAttachment;
-        setAttachmentImpl(GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
-        setAttachmentImpl(stencil.type(), GL_STENCIL_ATTACHMENT,
+        setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(),
+                          nullptr);
+        setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
                           getImageIndexIfTextureAttachment(stencil), stencil.getResource());
     }
     else if (mState.mWebGLDepthStencilAttachment.isAttached())
     {
         const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
-        setAttachmentImpl(depthStencil.type(), GL_DEPTH_ATTACHMENT,
+        setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
                           getImageIndexIfTextureAttachment(depthStencil),
                           depthStencil.getResource());
-        setAttachmentImpl(depthStencil.type(), GL_STENCIL_ATTACHMENT,
+        setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
                           getImageIndexIfTextureAttachment(depthStencil),
                           depthStencil.getResource());
     }
     else
     {
-        setAttachmentImpl(GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
-        setAttachmentImpl(GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
+        setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(),
+                          nullptr);
+        setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
+                          nullptr);
     }
 }
 
-void Framebuffer::setAttachmentImpl(GLenum type,
+void Framebuffer::setAttachmentImpl(const Context *context,
+                                    GLenum type,
                                     GLenum binding,
                                     const ImageIndex &textureIndex,
                                     FramebufferAttachmentObject *resource)
@@ -1206,10 +1230,10 @@
                 }
             }
 
-            updateAttachment(&mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
+            updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
                              &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
                              attachmentObj);
-            updateAttachment(&mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
+            updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
                              &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
                              attachmentObj);
             return;
@@ -1217,19 +1241,19 @@
 
         case GL_DEPTH:
         case GL_DEPTH_ATTACHMENT:
-            updateAttachment(&mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
+            updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
                              &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource);
             break;
 
         case GL_STENCIL:
         case GL_STENCIL_ATTACHMENT:
-            updateAttachment(&mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
+            updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
                              &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
                              resource);
             break;
 
         case GL_BACK:
-            mState.mColorAttachments[0].attach(type, binding, textureIndex, resource);
+            mState.mColorAttachments[0].attach(context, type, binding, textureIndex, resource);
             mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
             // No need for a resource binding for the default FBO, it's always complete.
             break;
@@ -1239,7 +1263,7 @@
             size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
             ASSERT(colorIndex < mState.mColorAttachments.size());
             size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
-            updateAttachment(&mState.mColorAttachments[colorIndex], dirtyBit,
+            updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
                              &mDirtyColorAttachmentBindings[colorIndex], type, binding,
                              textureIndex, resource);
 
@@ -1252,7 +1276,8 @@
     }
 }
 
-void Framebuffer::updateAttachment(FramebufferAttachment *attachment,
+void Framebuffer::updateAttachment(const Context *context,
+                                   FramebufferAttachment *attachment,
                                    size_t dirtyBit,
                                    OnAttachmentDirtyBinding *onDirtyBinding,
                                    GLenum type,
@@ -1260,7 +1285,7 @@
                                    const ImageIndex &textureIndex,
                                    FramebufferAttachmentObject *resource)
 {
-    attachment->attach(type, binding, textureIndex, resource);
+    attachment->attach(context, type, binding, textureIndex, resource);
     mDirtyBits.set(dirtyBit);
     BindResourceChannel(onDirtyBinding, resource);
 }
diff --git a/src/libANGLE/Framebuffer.h b/src/libANGLE/Framebuffer.h
index a8a9bb5..0a0b339 100644
--- a/src/libANGLE/Framebuffer.h
+++ b/src/libANGLE/Framebuffer.h
@@ -125,12 +125,12 @@
     // Constructor to build application-defined framebuffers
     Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id);
     // Constructor to build default framebuffers for a surface
-    Framebuffer(egl::Surface *surface);
+    Framebuffer(const egl::Display *display, egl::Surface *surface);
     // Constructor to build a fake default framebuffer when surfaceless
     Framebuffer(rx::GLImplFactory *factory);
 
     virtual ~Framebuffer();
-    void destroy(const Context *context);
+    void onDestroy(const Context *context);
     void destroyDefault(const egl::Display *display);
 
     void setLabel(const std::string &label) override;
@@ -207,9 +207,12 @@
 
     bool hasValidDepthStencil() const;
 
-    Error discard(size_t count, const GLenum *attachments);
-    Error invalidate(size_t count, const GLenum *attachments);
-    Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area);
+    Error discard(const Context *context, size_t count, const GLenum *attachments);
+    Error invalidate(const Context *context, size_t count, const GLenum *attachments);
+    Error invalidateSub(const Context *context,
+                        size_t count,
+                        const GLenum *attachments,
+                        const gl::Rectangle &area);
 
     Error clear(const gl::Context *context, GLbitfield mask);
     Error clearBufferfv(const gl::Context *context,
@@ -230,8 +233,8 @@
                         GLfloat depth,
                         GLint stencil);
 
-    GLenum getImplementationColorReadFormat() const;
-    GLenum getImplementationColorReadType() const;
+    GLenum getImplementationColorReadFormat(const Context *context) const;
+    GLenum getImplementationColorReadType(const Context *context) const;
     Error readPixels(const gl::Context *context,
                      const gl::Rectangle &area,
                      GLenum format,
@@ -276,18 +279,21 @@
 
   private:
     void detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId);
-    void detachMatchingAttachment(FramebufferAttachment *attachment,
+    void detachMatchingAttachment(const Context *context,
+                                  FramebufferAttachment *attachment,
                                   GLenum matchType,
                                   GLuint matchId,
                                   size_t dirtyBit);
     GLenum checkStatusImpl(const Context *context);
-    void commitWebGL1DepthStencilIfConsistent();
+    void commitWebGL1DepthStencilIfConsistent(const Context *context);
 
-    void setAttachmentImpl(GLenum type,
+    void setAttachmentImpl(const Context *context,
+                           GLenum type,
                            GLenum binding,
                            const ImageIndex &textureIndex,
                            FramebufferAttachmentObject *resource);
-    void updateAttachment(FramebufferAttachment *attachment,
+    void updateAttachment(const Context *context,
+                          FramebufferAttachment *attachment,
                           size_t dirtyBit,
                           OnAttachmentDirtyBinding *onDirtyBinding,
                           GLenum type,
diff --git a/src/libANGLE/FramebufferAttachment.cpp b/src/libANGLE/FramebufferAttachment.cpp
index aeea903..aaa3d05 100644
--- a/src/libANGLE/FramebufferAttachment.cpp
+++ b/src/libANGLE/FramebufferAttachment.cpp
@@ -55,38 +55,41 @@
 {
 }
 
-FramebufferAttachment::FramebufferAttachment(GLenum type,
+FramebufferAttachment::FramebufferAttachment(const Context *context,
+                                             GLenum type,
                                              GLenum binding,
                                              const ImageIndex &textureIndex,
                                              FramebufferAttachmentObject *resource)
     : mResource(nullptr)
 {
-    attach(type, binding, textureIndex, resource);
+    attach(context, type, binding, textureIndex, resource);
 }
 
-FramebufferAttachment::FramebufferAttachment(const FramebufferAttachment &other)
-    : mResource(nullptr)
+FramebufferAttachment::FramebufferAttachment(FramebufferAttachment &&other)
+    : FramebufferAttachment()
 {
-    attach(other.mType, other.mTarget.binding(), other.mTarget.textureIndex(), other.mResource);
+    *this = std::move(other);
 }
 
-FramebufferAttachment &FramebufferAttachment::operator=(const FramebufferAttachment &other)
+FramebufferAttachment &FramebufferAttachment::operator=(FramebufferAttachment &&other)
 {
-    attach(other.mType, other.mTarget.binding(), other.mTarget.textureIndex(), other.mResource);
+    std::swap(mType, other.mType);
+    std::swap(mTarget, other.mTarget);
+    std::swap(mResource, other.mResource);
     return *this;
 }
 
 FramebufferAttachment::~FramebufferAttachment()
 {
-    detach();
+    ASSERT(!isAttached());
 }
 
-void FramebufferAttachment::detach()
+void FramebufferAttachment::detach(const Context *context)
 {
     mType = GL_NONE;
     if (mResource != nullptr)
     {
-        mResource->onDetach();
+        mResource->onDetach(context);
         mResource = nullptr;
     }
 
@@ -94,24 +97,25 @@
     mTarget = Target();
 }
 
-void FramebufferAttachment::attach(GLenum type,
+void FramebufferAttachment::attach(const Context *context,
+                                   GLenum type,
                                    GLenum binding,
                                    const ImageIndex &textureIndex,
                                    FramebufferAttachmentObject *resource)
 {
     if (resource == nullptr)
     {
-        detach();
+        detach(context);
         return;
     }
 
     mType = type;
     mTarget = Target(binding, textureIndex);
-    resource->onAttach();
+    resource->onAttach(context);
 
     if (mResource != nullptr)
     {
-        mResource->onDetach();
+        mResource->onDetach(context);
     }
 
     mResource = resource;
@@ -236,11 +240,12 @@
 }
 
 Error FramebufferAttachmentObject::getAttachmentRenderTarget(
+    const Context *context,
     GLenum binding,
     const ImageIndex &imageIndex,
     rx::FramebufferAttachmentRenderTarget **rtOut) const
 {
-    return getAttachmentImpl()->getAttachmentRenderTarget(binding, imageIndex, rtOut);
+    return getAttachmentImpl()->getAttachmentRenderTarget(context, binding, imageIndex, rtOut);
 }
 
 angle::BroadcastChannel<> *FramebufferAttachmentObject::getDirtyChannel()
diff --git a/src/libANGLE/FramebufferAttachment.h b/src/libANGLE/FramebufferAttachment.h
index ead0bac..fcbecba 100644
--- a/src/libANGLE/FramebufferAttachment.h
+++ b/src/libANGLE/FramebufferAttachment.h
@@ -54,18 +54,20 @@
   public:
     FramebufferAttachment();
 
-    FramebufferAttachment(GLenum type,
+    FramebufferAttachment(const Context *context,
+                          GLenum type,
                           GLenum binding,
                           const ImageIndex &textureIndex,
                           FramebufferAttachmentObject *resource);
 
-    FramebufferAttachment(const FramebufferAttachment &other);
-    FramebufferAttachment &operator=(const FramebufferAttachment &other);
+    FramebufferAttachment(FramebufferAttachment &&other);
+    FramebufferAttachment &operator=(FramebufferAttachment &&other);
 
     ~FramebufferAttachment();
 
-    void detach();
-    void attach(GLenum type,
+    void detach(const Context *context);
+    void attach(const Context *context,
+                GLenum type,
                 GLenum binding,
                 const ImageIndex &textureIndex,
                 FramebufferAttachmentObject *resource);
@@ -108,19 +110,20 @@
 
     // "T" must be static_castable from FramebufferAttachmentRenderTarget
     template <typename T>
-    gl::Error getRenderTarget(T **rtOut) const
+    gl::Error getRenderTarget(const Context *context, T **rtOut) const
     {
         static_assert(std::is_base_of<rx::FramebufferAttachmentRenderTarget, T>(),
                       "Invalid RenderTarget class.");
         return getRenderTargetImpl(
-            reinterpret_cast<rx::FramebufferAttachmentRenderTarget **>(rtOut));
+            context, reinterpret_cast<rx::FramebufferAttachmentRenderTarget **>(rtOut));
     }
 
     bool operator==(const FramebufferAttachment &other) const;
     bool operator!=(const FramebufferAttachment &other) const;
 
   private:
-    gl::Error getRenderTargetImpl(rx::FramebufferAttachmentRenderTarget **rtOut) const;
+    gl::Error getRenderTargetImpl(const Context *context,
+                                  rx::FramebufferAttachmentRenderTarget **rtOut) const;
 
     // A framebuffer attachment points to one of three types of resources: Renderbuffers,
     // Textures and egl::Surface. The "Target" struct indicates which part of the
@@ -161,11 +164,12 @@
                                               const ImageIndex &imageIndex) const = 0;
     virtual GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const      = 0;
 
-    virtual void onAttach() = 0;
-    virtual void onDetach() = 0;
+    virtual void onAttach(const Context *context) = 0;
+    virtual void onDetach(const Context *context) = 0;
     virtual GLuint getId() const = 0;
 
-    Error getAttachmentRenderTarget(GLenum binding,
+    Error getAttachmentRenderTarget(const Context *context,
+                                    GLenum binding,
                                     const ImageIndex &imageIndex,
                                     rx::FramebufferAttachmentRenderTarget **rtOut) const;
 
@@ -196,10 +200,12 @@
 }
 
 inline gl::Error FramebufferAttachment::getRenderTargetImpl(
+    const Context *context,
     rx::FramebufferAttachmentRenderTarget **rtOut) const
 {
     ASSERT(mResource);
-    return mResource->getAttachmentRenderTarget(mTarget.binding(), mTarget.textureIndex(), rtOut);
+    return mResource->getAttachmentRenderTarget(context, mTarget.binding(), mTarget.textureIndex(),
+                                                rtOut);
 }
 
 } // namespace gl
diff --git a/src/libANGLE/Image.cpp b/src/libANGLE/Image.cpp
index 194fad1..a99a8bb 100644
--- a/src/libANGLE/Image.cpp
+++ b/src/libANGLE/Image.cpp
@@ -53,32 +53,33 @@
 {
     // EGL images should hold a ref to their targets and siblings, a Texture should not be deletable
     // while it is attached to an EGL image.
+    // Child class should orphan images before destruction.
     ASSERT(mSourcesOf.empty());
-    orphanImages();
+    ASSERT(mTargetOf.get() == nullptr);
 }
 
-void ImageSibling::setTargetImage(egl::Image *imageTarget)
+void ImageSibling::setTargetImage(const gl::Context *context, egl::Image *imageTarget)
 {
     ASSERT(imageTarget != nullptr);
-    mTargetOf.set(imageTarget);
+    mTargetOf.set(context, imageTarget);
     imageTarget->addTargetSibling(this);
 }
 
-gl::Error ImageSibling::orphanImages()
+gl::Error ImageSibling::orphanImages(const gl::Context *context)
 {
     if (mTargetOf.get() != nullptr)
     {
         // Can't be a target and have sources.
         ASSERT(mSourcesOf.empty());
 
-        ANGLE_TRY(mTargetOf->orphanSibling(this));
-        mTargetOf.set(nullptr);
+        ANGLE_TRY(mTargetOf->orphanSibling(context, this));
+        mTargetOf.set(context, nullptr);
     }
     else
     {
         for (auto &sourceImage : mSourcesOf)
         {
-            ANGLE_TRY(sourceImage->orphanSibling(this));
+            ANGLE_TRY(sourceImage->orphanSibling(context, this));
         }
         mSourcesOf.clear();
     }
@@ -99,9 +100,8 @@
 }
 
 ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
-    : imageIndex(GetImageIndex(target, attribs)), source(), targets()
+    : imageIndex(GetImageIndex(target, attribs)), source(buffer), targets()
 {
-    source.set(buffer);
 }
 
 Image::Image(rx::EGLImplFactory *factory,
@@ -118,7 +118,7 @@
     mState.source->addImageSource(this);
 }
 
-Image::~Image()
+void Image::onDestroy(const gl::Context *context)
 {
     SafeDelete(mImplementation);
 
@@ -130,25 +130,30 @@
     if (mState.source.get() != nullptr)
     {
         mState.source->removeImageSource(this);
-        mState.source.set(nullptr);
+        mState.source.set(context, nullptr);
     }
 }
 
+Image::~Image()
+{
+    ASSERT(!mImplementation);
+}
+
 void Image::addTargetSibling(ImageSibling *sibling)
 {
     mState.targets.insert(sibling);
 }
 
-gl::Error Image::orphanSibling(ImageSibling *sibling)
+gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
 {
     // notify impl
-    ANGLE_TRY(mImplementation->orphan(sibling));
+    ANGLE_TRY(mImplementation->orphan(context, sibling));
 
     if (mState.source.get() == sibling)
     {
         // If the sibling is the source, it cannot be a target.
         ASSERT(mState.targets.find(sibling) == mState.targets.end());
-        mState.source.set(nullptr);
+        mState.source.set(context, nullptr);
     }
     else
     {
diff --git a/src/libANGLE/Image.h b/src/libANGLE/Image.h
index adb5f23..ac90738 100644
--- a/src/libANGLE/Image.h
+++ b/src/libANGLE/Image.h
@@ -31,7 +31,7 @@
 // Only currently Renderbuffers and Textures can be bound with images. This makes the relationship
 // explicit, and also ensures that an image sibling can determine if it's been initialized or not,
 // which is important for the robust resource init extension with Textures and EGLImages.
-class ImageSibling : public RefCountObject, public gl::FramebufferAttachmentObject
+class ImageSibling : public gl::RefCountObject, public gl::FramebufferAttachmentObject
 {
   public:
     ImageSibling(GLuint id);
@@ -39,10 +39,10 @@
 
   protected:
     // Set the image target of this sibling
-    void setTargetImage(egl::Image *imageTarget);
+    void setTargetImage(const gl::Context *context, egl::Image *imageTarget);
 
     // Orphan all EGL image sources and targets
-    gl::Error orphanImages();
+    gl::Error orphanImages(const gl::Context *context);
 
   private:
     friend class Image;
@@ -54,7 +54,7 @@
     void removeImageSource(egl::Image *imageSource);
 
     std::set<Image *> mSourcesOf;
-    BindingPointer<Image> mTargetOf;
+    gl::BindingPointer<Image> mTargetOf;
 };
 
 struct ImageState : private angle::NonCopyable
@@ -62,17 +62,19 @@
     ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs);
 
     gl::ImageIndex imageIndex;
-    BindingPointer<ImageSibling> source;
+    gl::BindingPointer<ImageSibling> source;
     std::set<ImageSibling *> targets;
 };
 
-class Image final : public RefCountObject
+class Image final : public gl::RefCountObject
 {
   public:
     Image(rx::EGLImplFactory *factory,
           EGLenum target,
           ImageSibling *buffer,
           const AttributeMap &attribs);
+
+    void onDestroy(const gl::Context *context) override;
     ~Image();
 
     const gl::Format &getFormat() const;
@@ -93,7 +95,7 @@
 
     // Called from ImageSibling only to notify the image that a sibling (source or target) has
     // been respecified and state tracking should be updated.
-    gl::Error orphanSibling(ImageSibling *sibling);
+    gl::Error orphanSibling(const gl::Context *context, ImageSibling *sibling);
 
     ImageState mState;
     rx::ImageImpl *mImplementation;
diff --git a/src/libANGLE/Image_unittest.cpp b/src/libANGLE/Image_unittest.cpp
index 8d70b57..8c3601e1a 100644
--- a/src/libANGLE/Image_unittest.cpp
+++ b/src/libANGLE/Image_unittest.cpp
@@ -60,7 +60,7 @@
     EXPECT_CALL(*renderbufferImpl, setStorageEGLImageTarget(_))
         .WillOnce(Return(gl::NoError()))
         .RetiresOnSaturation();
-    renderbuffer->setStorageEGLImageTarget(image);
+    renderbuffer->setStorageEGLImageTarget(nullptr, image);
 
     // Verify that the renderbuffer added a ref to the image and the image did not add a ref to
     // the renderbuffer
@@ -70,14 +70,14 @@
 
     // Simulate deletion of the texture and verify that it still exists because the image holds a
     // ref
-    texture->release();
+    texture->release(nullptr);
     EXPECT_EQ(1u, texture->getRefCount());
     EXPECT_EQ(2u, image->getRefCount());
     EXPECT_EQ(1u, renderbuffer->getRefCount());
 
     // Simulate deletion of the image and verify that it still exists because the renderbuffer holds
     // a ref
-    image->release();
+    image->release(nullptr);
     EXPECT_EQ(1u, texture->getRefCount());
     EXPECT_EQ(1u, image->getRefCount());
     EXPECT_EQ(1u, renderbuffer->getRefCount());
@@ -85,12 +85,12 @@
     // Simulate deletion of the renderbuffer and verify that the deletion cascades to all objects
     rx::MockImageImpl *imageImpl = static_cast<rx::MockImageImpl *>(image->getImplementation());
     EXPECT_CALL(*imageImpl, destructor()).Times(1).RetiresOnSaturation();
-    EXPECT_CALL(*imageImpl, orphan(_)).WillOnce(Return(gl::NoError())).RetiresOnSaturation();
+    EXPECT_CALL(*imageImpl, orphan(_, _)).WillOnce(Return(gl::NoError())).RetiresOnSaturation();
 
     EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
     EXPECT_CALL(*renderbufferImpl, destructor()).Times(1).RetiresOnSaturation();
 
-    renderbuffer->release();
+    renderbuffer->release(nullptr);
 }
 
 // Verify that respecifiying textures releases references to the Image.
@@ -128,7 +128,7 @@
 
     // Respecify the texture and verify that the image releases its reference
     rx::MockImageImpl *imageImpl = static_cast<rx::MockImageImpl *>(image->getImplementation());
-    EXPECT_CALL(*imageImpl, orphan(_)).WillOnce(Return(gl::NoError())).RetiresOnSaturation();
+    EXPECT_CALL(*imageImpl, orphan(_, _)).WillOnce(Return(gl::NoError())).RetiresOnSaturation();
     EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _, _))
         .WillOnce(Return(gl::NoError()))
         .RetiresOnSaturation();
@@ -141,12 +141,12 @@
 
     // Delete the texture and verify that the image still exists
     EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
-    texture->release();
+    texture->release(nullptr);
 
     EXPECT_EQ(1u, image->getRefCount());
 
     // Delete the image
     EXPECT_CALL(*imageImpl, destructor()).Times(1).RetiresOnSaturation();
-    image->release();
+    image->release(nullptr);
 }
 }  // namespace angle
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index fdd3164..df2137b 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -412,12 +412,10 @@
 
 Program::~Program()
 {
-    ASSERT(!mState.mAttachedVertexShader && !mState.mAttachedFragmentShader &&
-           !mState.mAttachedComputeShader);
-    SafeDelete(mProgram);
+    ASSERT(!mProgram);
 }
 
-void Program::destroy(const Context *context)
+void Program::onDestroy(const Context *context)
 {
     if (mState.mAttachedVertexShader != nullptr)
     {
@@ -438,6 +436,12 @@
     }
 
     mProgram->destroy(context);
+
+    ASSERT(!mState.mAttachedVertexShader && !mState.mAttachedFragmentShader &&
+           !mState.mAttachedComputeShader);
+    SafeDelete(mProgram);
+
+    delete this;
 }
 
 void Program::setLabel(const std::string &label)
diff --git a/src/libANGLE/Program.h b/src/libANGLE/Program.h
index 4bfe401..9a59f15 100644
--- a/src/libANGLE/Program.h
+++ b/src/libANGLE/Program.h
@@ -308,8 +308,7 @@
 {
   public:
     Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle);
-    ~Program();
-    void destroy(const Context *context);
+    void onDestroy(const Context *context);
 
     GLuint id() const { return mHandle; }
 
@@ -495,6 +494,8 @@
     };
 
   private:
+    ~Program();
+
     struct VaryingRef
     {
         const sh::Varying *get() const { return vertex ? vertex : fragment; }
diff --git a/src/libANGLE/Query.h b/src/libANGLE/Query.h
index 5486f98..7a51917 100644
--- a/src/libANGLE/Query.h
+++ b/src/libANGLE/Query.h
@@ -29,6 +29,7 @@
 {
   public:
     Query(rx::QueryImpl *impl, GLuint id);
+    void destroy(const gl::Context *context) {}
     virtual ~Query();
 
     void setLabel(const std::string &label) override;
diff --git a/src/libANGLE/RefCountObject.h b/src/libANGLE/RefCountObject.h
index 112312e..4bafda5 100644
--- a/src/libANGLE/RefCountObject.h
+++ b/src/libANGLE/RefCountObject.h
@@ -21,12 +21,12 @@
 namespace gl
 {
 class Context;
-}
 
 class RefCountObjectNoID : angle::NonCopyable
 {
   public:
     RefCountObjectNoID() : mRefCount(0) {}
+    virtual void onDestroy(const gl::Context *context) {}
 
     void addRef() const { ++mRefCount; }
 
@@ -40,38 +40,44 @@
         }
     }
 
-    // A specialized release method for objects which need a destroy context.
-    void release(const gl::Context *context)
-    {
-        ASSERT(mRefCount > 0);
-        if (--mRefCount == 0)
-        {
-            destroy(context);
-            delete this;
-        }
-    }
-
     size_t getRefCount() const { return mRefCount; }
 
   protected:
     virtual ~RefCountObjectNoID() { ASSERT(mRefCount == 0); }
-    virtual void destroy(const gl::Context *context) {}
 
-  private:
     mutable std::size_t mRefCount;
 };
 
-class RefCountObject : public RefCountObjectNoID
+template <class ObjectType>
+class BindingPointer;
+
+class RefCountObject : RefCountObjectNoID
 {
   public:
     explicit RefCountObject(GLuint id) : mId(id) {}
 
     GLuint id() const { return mId; }
 
+    // A specialized release method for objects which need a destroy context.
+    void release(const gl::Context *context)
+    {
+        ASSERT(mRefCount > 0);
+        if (--mRefCount == 0)
+        {
+            onDestroy(context);
+            delete this;
+        }
+    }
+
+    using RefCountObjectNoID::addRef;
+    using RefCountObjectNoID::getRefCount;
+
   protected:
     ~RefCountObject() override {}
 
   private:
+    template <class ObjectType>
+    friend class BindingPointer;
     GLuint mId;
 };
 
@@ -84,15 +90,17 @@
     {
     }
 
-    BindingPointer(const BindingPointer<ObjectType> &other)
-        : mObject(nullptr)
+    BindingPointer(ObjectType *object) : mObject(object) { mObject->addRef(); }
+
+    BindingPointer(const BindingPointer<ObjectType> &other) : mObject(other.mObject)
     {
-        set(other.mObject);
+        mObject->addRef();
     }
 
-    void operator=(const BindingPointer<ObjectType> &other)
+    BindingPointer &operator=(BindingPointer<ObjectType> &&other)
     {
-        set(other.mObject);
+        std::swap(mObject, other.mObject);
+        return *this;
     }
 
     virtual ~BindingPointer()
@@ -101,11 +109,12 @@
         ASSERT(mObject == nullptr);
     }
 
-    virtual void set(ObjectType *newObject)
+    virtual void set(const Context *context, ObjectType *newObject)
     {
         // addRef first in case newObject == mObject and this is the last reference to it.
         if (newObject != nullptr) reinterpret_cast<const RefCountObject*>(newObject)->addRef();
-        if (mObject != nullptr) reinterpret_cast<const RefCountObject*>(mObject)->release();
+        if (mObject != nullptr)
+            reinterpret_cast<RefCountObject *>(mObject)->release(context);
         mObject = newObject;
     }
 
@@ -131,16 +140,16 @@
   public:
     OffsetBindingPointer() : mOffset(0), mSize(0) { }
 
-    void set(ObjectType *newObject) override
+    void set(const Context *context, ObjectType *newObject) override
     {
-        BindingPointer<ObjectType>::set(newObject);
+        BindingPointer<ObjectType>::set(context, newObject);
         mOffset = 0;
         mSize = 0;
     }
 
-    void set(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
+    void set(const Context *context, ObjectType *newObject, GLintptr offset, GLsizeiptr size)
     {
-        BindingPointer<ObjectType>::set(newObject);
+        BindingPointer<ObjectType>::set(context, newObject);
         mOffset = offset;
         mSize = size;
     }
@@ -162,5 +171,6 @@
     GLintptr mOffset;
     GLsizeiptr mSize;
 };
+}  // namespace gl
 
 #endif   // LIBANGLE_REFCOUNTOBJECT_H_
diff --git a/src/libANGLE/Renderbuffer.cpp b/src/libANGLE/Renderbuffer.cpp
index 68b011d..3a98114 100644
--- a/src/libANGLE/Renderbuffer.cpp
+++ b/src/libANGLE/Renderbuffer.cpp
@@ -30,6 +30,13 @@
 {
 }
 
+void Renderbuffer::onDestroy(const Context *context)
+{
+    auto err = orphanImages(context);
+    // TODO(jmadill): Handle error.
+    ASSERT(!err.isError());
+}
+
 Renderbuffer::~Renderbuffer()
 {
     SafeDelete(mRenderbuffer);
@@ -45,9 +52,12 @@
     return mLabel;
 }
 
-Error Renderbuffer::setStorage(GLenum internalformat, size_t width, size_t height)
+Error Renderbuffer::setStorage(const Context *context,
+                               GLenum internalformat,
+                               size_t width,
+                               size_t height)
 {
-    orphanImages();
+    ANGLE_TRY(orphanImages(context));
 
     ANGLE_TRY(mRenderbuffer->setStorage(internalformat, width, height));
 
@@ -61,9 +71,13 @@
     return NoError();
 }
 
-Error Renderbuffer::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
+Error Renderbuffer::setStorageMultisample(const Context *context,
+                                          size_t samples,
+                                          GLenum internalformat,
+                                          size_t width,
+                                          size_t height)
 {
-    orphanImages();
+    ANGLE_TRY(orphanImages(context));
 
     ANGLE_TRY(mRenderbuffer->setStorageMultisample(samples, internalformat, width, height));
 
@@ -77,13 +91,13 @@
     return NoError();
 }
 
-Error Renderbuffer::setStorageEGLImageTarget(egl::Image *image)
+Error Renderbuffer::setStorageEGLImageTarget(const Context *context, egl::Image *image)
 {
-    orphanImages();
+    ANGLE_TRY(orphanImages(context));
 
     ANGLE_TRY(mRenderbuffer->setStorageEGLImageTarget(image));
 
-    setTargetImage(image);
+    setTargetImage(context, image);
 
     mWidth          = static_cast<GLsizei>(image->getWidth());
     mHeight         = static_cast<GLsizei>(image->getHeight());
@@ -151,14 +165,14 @@
     return mFormat.info->stencilBits;
 }
 
-void Renderbuffer::onAttach()
+void Renderbuffer::onAttach(const Context *context)
 {
     addRef();
 }
 
-void Renderbuffer::onDetach()
+void Renderbuffer::onDetach(const Context *context)
 {
-    release();
+    release(context);
 }
 
 GLuint Renderbuffer::getId() const
diff --git a/src/libANGLE/Renderbuffer.h b/src/libANGLE/Renderbuffer.h
index da17125..07e9404 100644
--- a/src/libANGLE/Renderbuffer.h
+++ b/src/libANGLE/Renderbuffer.h
@@ -34,14 +34,18 @@
     Renderbuffer(rx::RenderbufferImpl *impl, GLuint id);
     virtual ~Renderbuffer();
 
-    void destroy(const Context *context) override {}
+    void onDestroy(const Context *context) override;
 
     void setLabel(const std::string &label) override;
     const std::string &getLabel() const override;
 
-    Error setStorage(GLenum internalformat, size_t width, size_t height);
-    Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height);
-    Error setStorageEGLImageTarget(egl::Image *imageTarget);
+    Error setStorage(const Context *context, GLenum internalformat, size_t width, size_t height);
+    Error setStorageMultisample(const Context *context,
+                                size_t samples,
+                                GLenum internalformat,
+                                size_t width,
+                                size_t height);
+    Error setStorageEGLImageTarget(const Context *context, egl::Image *imageTarget);
 
     rx::RenderbufferImpl *getImplementation() const;
 
@@ -68,8 +72,8 @@
         return getSamples();
     }
 
-    void onAttach() override;
-    void onDetach() override;
+    void onAttach(const Context *context) override;
+    void onDetach(const Context *context) override;
     GLuint getId() const override;
 
   private:
diff --git a/src/libANGLE/ResourceManager.cpp b/src/libANGLE/ResourceManager.cpp
index 18e1fd2..d8690b7 100644
--- a/src/libANGLE/ResourceManager.cpp
+++ b/src/libANGLE/ResourceManager.cpp
@@ -92,8 +92,7 @@
 
     if (objectIter->second != nullptr)
     {
-        objectIter->second->destroy(context);
-        ImplT::DeleteObject(objectIter->second);
+        ImplT::DeleteObject(context, objectIter->second);
     }
 
     // Requires an explicit this-> because of C++ template rules.
@@ -168,9 +167,9 @@
 }
 
 // static
-void BufferManager::DeleteObject(Buffer *buffer)
+void BufferManager::DeleteObject(const Context *context, Buffer *buffer)
 {
-    buffer->release();
+    buffer->release(context);
 }
 
 GLuint BufferManager::createBuffer()
@@ -262,8 +261,7 @@
     if (object->getRefCount() == 0)
     {
         mHandleAllocator.release(id);
-        object->destroy(context);
-        SafeDelete(object);
+        object->onDestroy(context);
         objectMap->erase(iter);
     }
     else
@@ -283,9 +281,9 @@
 }
 
 // static
-void TextureManager::DeleteObject(Texture *texture)
+void TextureManager::DeleteObject(const Context *context, Texture *texture)
 {
-    texture->release();
+    texture->release(context);
 }
 
 GLuint TextureManager::createTexture()
@@ -326,9 +324,9 @@
 }
 
 // static
-void RenderbufferManager::DeleteObject(Renderbuffer *renderbuffer)
+void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer)
 {
-    renderbuffer->release();
+    renderbuffer->release(context);
 }
 
 GLuint RenderbufferManager::createRenderbuffer()
@@ -357,9 +355,9 @@
 }
 
 // static
-void SamplerManager::DeleteObject(Sampler *sampler)
+void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
 {
-    sampler->release();
+    sampler->release(context);
 }
 
 GLuint SamplerManager::createSampler()
@@ -380,9 +378,9 @@
 // FenceSyncManager Implementation.
 
 // static
-void FenceSyncManager::DeleteObject(FenceSync *fenceSync)
+void FenceSyncManager::DeleteObject(const Context *context, FenceSync *fenceSync)
 {
-    fenceSync->release();
+    fenceSync->release(context);
 }
 
 GLuint FenceSyncManager::createFenceSync(rx::GLImplFactory *factory)
@@ -477,11 +475,12 @@
 }
 
 // static
-void FramebufferManager::DeleteObject(Framebuffer *framebuffer)
+void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
 {
     // Default framebuffer are owned by their respective Surface
     if (framebuffer->id() != 0)
     {
+        framebuffer->onDestroy(context);
         delete framebuffer;
     }
 }
diff --git a/src/libANGLE/ResourceManager.h b/src/libANGLE/ResourceManager.h
index 82d2307..3228fda 100644
--- a/src/libANGLE/ResourceManager.h
+++ b/src/libANGLE/ResourceManager.h
@@ -111,7 +111,7 @@
 
     // TODO(jmadill): Investigate design which doesn't expose these methods publicly.
     static Buffer *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle);
-    static void DeleteObject(Buffer *buffer);
+    static void DeleteObject(const Context *context, Buffer *buffer);
 
   protected:
     ~BufferManager() override {}
@@ -158,7 +158,7 @@
     }
 
     static Texture *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle, GLenum target);
-    static void DeleteObject(Texture *texture);
+    static void DeleteObject(const Context *context, Texture *texture);
 
   protected:
     ~TextureManager() override {}
@@ -178,7 +178,7 @@
     }
 
     static Renderbuffer *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle);
-    static void DeleteObject(Renderbuffer *renderbuffer);
+    static void DeleteObject(const Context *context, Renderbuffer *renderbuffer);
 
   protected:
     ~RenderbufferManager() override {}
@@ -197,7 +197,7 @@
     }
 
     static Sampler *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle);
-    static void DeleteObject(Sampler *sampler);
+    static void DeleteObject(const Context *context, Sampler *sampler);
 
   protected:
     ~SamplerManager() override {}
@@ -209,7 +209,7 @@
     GLuint createFenceSync(rx::GLImplFactory *factory);
     FenceSync *getFenceSync(GLuint handle);
 
-    static void DeleteObject(FenceSync *fenceSync);
+    static void DeleteObject(const Context *context, FenceSync *fenceSync);
 
   protected:
     ~FenceSyncManager() override {}
@@ -252,7 +252,7 @@
     static Framebuffer *AllocateNewObject(rx::GLImplFactory *factory,
                                           GLuint handle,
                                           const Caps &caps);
-    static void DeleteObject(Framebuffer *framebuffer);
+    static void DeleteObject(const Context *context, Framebuffer *framebuffer);
 
   protected:
     ~FramebufferManager() override {}
diff --git a/src/libANGLE/Sampler.h b/src/libANGLE/Sampler.h
index 0e5ff8a..e281021 100644
--- a/src/libANGLE/Sampler.h
+++ b/src/libANGLE/Sampler.h
@@ -29,7 +29,7 @@
     Sampler(rx::GLImplFactory *factory, GLuint id);
     ~Sampler() override;
 
-    void destroy(const Context *context) override {}
+    void onDestroy(const Context *context) override {}
 
     void setLabel(const std::string &label) override;
     const std::string &getLabel() const override;
diff --git a/src/libANGLE/Shader.cpp b/src/libANGLE/Shader.cpp
index 929aace..b44339c 100644
--- a/src/libANGLE/Shader.cpp
+++ b/src/libANGLE/Shader.cpp
@@ -104,9 +104,16 @@
     ASSERT(mImplementation);
 }
 
+void Shader::onDestroy(const gl::Context *context)
+{
+    mBoundCompiler.set(context, nullptr);
+    mImplementation.reset(nullptr);
+    delete this;
+}
+
 Shader::~Shader()
 {
-    mBoundCompiler.set(nullptr);
+    ASSERT(!mImplementation);
 }
 
 void Shader::setLabel(const std::string &label)
@@ -267,7 +274,7 @@
     mState.mActiveOutputVariables.clear();
 
     mState.mCompileStatus = CompileStatus::COMPILE_REQUESTED;
-    mBoundCompiler.set(context->getCompiler());
+    mBoundCompiler.set(context, context->getCompiler());
 
     // Cache the compile source and options for compilation. Must be done now, since the source
     // can change before the link call or another call that resolves the compile.
diff --git a/src/libANGLE/Shader.h b/src/libANGLE/Shader.h
index 906cc40..aa181bd 100644
--- a/src/libANGLE/Shader.h
+++ b/src/libANGLE/Shader.h
@@ -104,8 +104,7 @@
            GLenum type,
            GLuint handle);
 
-    void destroy(const Context *context) {}
-    virtual ~Shader();
+    void onDestroy(const Context *context);
 
     void setLabel(const std::string &label) override;
     const std::string &getLabel() const override;
@@ -152,6 +151,7 @@
     const sh::WorkGroupSize &getWorkGroupSize(const Context *context);
 
   private:
+    virtual ~Shader();
     static void GetSourceImpl(const std::string &source,
                               GLsizei bufSize,
                               GLsizei *length,
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index 91ee0bd..c5e6e2c 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -71,14 +71,16 @@
 {
 }
 
-void State::initialize(const Caps &caps,
-                       const Extensions &extensions,
-                       const Version &clientVersion,
+void State::initialize(const Context *context,
                        bool debug,
                        bool bindGeneratesResource,
                        bool clientArraysEnabled,
                        bool robustResourceInit)
 {
+    const Caps &caps             = context->getCaps();
+    const Extensions &extensions = context->getExtensions();
+    const Version &clientVersion = context->getClientVersion();
+
     mMaxDrawBuffers = caps.maxDrawBuffers;
     mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
 
@@ -152,11 +154,11 @@
 
     mSamplers.resize(caps.maxCombinedTextureImageUnits);
 
-    mActiveQueries[GL_ANY_SAMPLES_PASSED].set(nullptr);
-    mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(nullptr);
-    mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(nullptr);
-    mActiveQueries[GL_TIME_ELAPSED_EXT].set(nullptr);
-    mActiveQueries[GL_COMMANDS_COMPLETED_CHROMIUM].set(nullptr);
+    mActiveQueries[GL_ANY_SAMPLES_PASSED].set(context, nullptr);
+    mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(context, nullptr);
+    mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(context, nullptr);
+    mActiveQueries[GL_TIME_ELAPSED_EXT].set(context, nullptr);
+    mActiveQueries[GL_COMMANDS_COMPLETED_CHROMIUM].set(context, nullptr);
 
     mProgram = nullptr;
 
@@ -192,17 +194,17 @@
         TextureBindingVector &textureVector = bindingVec->second;
         for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
         {
-            textureVector[textureIdx].set(nullptr);
+            textureVector[textureIdx].set(context, nullptr);
         }
     }
     for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++)
     {
-        mSamplers[samplerIdx].set(nullptr);
+        mSamplers[samplerIdx].set(context, nullptr);
     }
 
-    mArrayBuffer.set(nullptr);
-    mDrawIndirectBuffer.set(nullptr);
-    mRenderbuffer.set(nullptr);
+    mArrayBuffer.set(context, nullptr);
+    mDrawIndirectBuffer.set(context, nullptr);
+    mRenderbuffer.set(context, nullptr);
 
     if (mProgram)
     {
@@ -210,35 +212,35 @@
     }
     mProgram = nullptr;
 
-    mTransformFeedback.set(nullptr);
+    mTransformFeedback.set(context, nullptr);
 
     for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++)
     {
-        i->second.set(nullptr);
+        i->second.set(context, nullptr);
     }
 
-    mGenericUniformBuffer.set(nullptr);
+    mGenericUniformBuffer.set(context, nullptr);
     for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr)
     {
-        bufItr->set(nullptr);
+        bufItr->set(context, nullptr);
     }
 
-    mCopyReadBuffer.set(nullptr);
-    mCopyWriteBuffer.set(nullptr);
+    mCopyReadBuffer.set(context, nullptr);
+    mCopyWriteBuffer.set(context, nullptr);
 
-    mPack.pixelBuffer.set(nullptr);
-    mUnpack.pixelBuffer.set(nullptr);
+    mPack.pixelBuffer.set(context, nullptr);
+    mUnpack.pixelBuffer.set(context, nullptr);
 
-    mGenericAtomicCounterBuffer.set(nullptr);
+    mGenericAtomicCounterBuffer.set(context, nullptr);
     for (auto &buf : mAtomicCounterBuffers)
     {
-        buf.set(nullptr);
+        buf.set(context, nullptr);
     }
 
-    mGenericShaderStorageBuffer.set(nullptr);
+    mGenericShaderStorageBuffer.set(context, nullptr);
     for (auto &buf : mShaderStorageBuffers)
     {
-        buf.set(nullptr);
+        buf.set(context, nullptr);
     }
 
     mProgram = nullptr;
@@ -738,9 +740,9 @@
     return static_cast<unsigned int>(mActiveSampler);
 }
 
-void State::setSamplerTexture(GLenum type, Texture *texture)
+void State::setSamplerTexture(const Context *context, GLenum type, Texture *texture)
 {
-    mSamplerTextures[type][mActiveSampler].set(texture);
+    mSamplerTextures[type][mActiveSampler].set(context, texture);
 }
 
 Texture *State::getTargetTexture(GLenum target) const
@@ -787,7 +789,7 @@
                 auto it = zeroTextures.find(textureType);
                 ASSERT(it != zeroTextures.end());
                 // Zero textures are the "default" textures instead of NULL
-                binding.set(it->second.get());
+                binding.set(context, it->second.get());
             }
         }
     }
@@ -808,7 +810,7 @@
     }
 }
 
-void State::initializeZeroTextures(const TextureMap &zeroTextures)
+void State::initializeZeroTextures(const Context *context, const TextureMap &zeroTextures)
 {
     for (const auto &zeroTexture : zeroTextures)
     {
@@ -816,14 +818,14 @@
 
         for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit)
         {
-            samplerTextureArray[textureUnit].set(zeroTexture.second.get());
+            samplerTextureArray[textureUnit].set(context, zeroTexture.second.get());
         }
     }
 }
 
-void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler)
+void State::setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler)
 {
-    mSamplers[textureUnit].set(sampler);
+    mSamplers[textureUnit].set(context, sampler);
 }
 
 GLuint State::getSamplerId(GLuint textureUnit) const
@@ -837,7 +839,7 @@
     return mSamplers[textureUnit].get();
 }
 
-void State::detachSampler(GLuint sampler)
+void State::detachSampler(const Context *context, GLuint sampler)
 {
     // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124:
     // If a sampler object that is currently bound to one or more texture units is
@@ -848,14 +850,14 @@
         BindingPointer<Sampler> &samplerBinding = mSamplers[textureUnit];
         if (samplerBinding.id() == sampler)
         {
-            samplerBinding.set(nullptr);
+            samplerBinding.set(context, nullptr);
         }
     }
 }
 
-void State::setRenderbufferBinding(Renderbuffer *renderbuffer)
+void State::setRenderbufferBinding(const Context *context, Renderbuffer *renderbuffer)
 {
-    mRenderbuffer.set(renderbuffer);
+    mRenderbuffer.set(context, renderbuffer);
 }
 
 GLuint State::getRenderbufferId() const
@@ -876,7 +878,7 @@
 
     if (mRenderbuffer.id() == renderbuffer)
     {
-        mRenderbuffer.set(nullptr);
+        mRenderbuffer.set(context, nullptr);
     }
 
     // [OpenGL ES 2.0.24] section 4.4 page 111:
@@ -1012,18 +1014,19 @@
     return false;
 }
 
-void State::setElementArrayBuffer(Buffer *buffer)
+void State::setElementArrayBuffer(const Context *context, Buffer *buffer)
 {
-    getVertexArray()->setElementArrayBuffer(buffer);
+    getVertexArray()->setElementArrayBuffer(context, buffer);
     mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
 }
 
-void State::bindVertexBuffer(GLuint bindingIndex,
+void State::bindVertexBuffer(const Context *context,
+                             GLuint bindingIndex,
                              Buffer *boundBuffer,
                              GLintptr offset,
                              GLsizei stride)
 {
-    getVertexArray()->bindVertexBuffer(bindingIndex, boundBuffer, offset, stride);
+    getVertexArray()->bindVertexBuffer(context, bindingIndex, boundBuffer, offset, stride);
     mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
 }
 
@@ -1074,9 +1077,10 @@
     return mProgram;
 }
 
-void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback)
+void State::setTransformFeedbackBinding(const Context *context,
+                                        TransformFeedback *transformFeedback)
 {
-    mTransformFeedback.set(transformFeedback);
+    mTransformFeedback.set(context, transformFeedback);
 }
 
 TransformFeedback *State::getCurrentTransformFeedback() const
@@ -1090,11 +1094,11 @@
     return curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused();
 }
 
-bool State::removeTransformFeedbackBinding(GLuint transformFeedback)
+bool State::removeTransformFeedbackBinding(const Context *context, GLuint transformFeedback)
 {
     if (mTransformFeedback.id() == transformFeedback)
     {
-        mTransformFeedback.set(nullptr);
+        mTransformFeedback.set(context, nullptr);
         return true;
     }
 
@@ -1128,9 +1132,9 @@
     return false;
 }
 
-void State::setActiveQuery(GLenum target, Query *query)
+void State::setActiveQuery(const Context *context, GLenum target, Query *query)
 {
-    mActiveQueries[target].set(query);
+    mActiveQueries[target].set(context, query);
 }
 
 GLuint State::getActiveQueryId(GLenum target) const
@@ -1149,9 +1153,9 @@
     return it->second.get();
 }
 
-void State::setArrayBufferBinding(Buffer *buffer)
+void State::setArrayBufferBinding(const Context *context, Buffer *buffer)
 {
-    mArrayBuffer.set(buffer);
+    mArrayBuffer.set(context, buffer);
 }
 
 GLuint State::getArrayBufferId() const
@@ -1159,20 +1163,24 @@
     return mArrayBuffer.id();
 }
 
-void State::setDrawIndirectBufferBinding(Buffer *buffer)
+void State::setDrawIndirectBufferBinding(const Context *context, Buffer *buffer)
 {
-    mDrawIndirectBuffer.set(buffer);
+    mDrawIndirectBuffer.set(context, buffer);
     mDirtyBits.set(DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING);
 }
 
-void State::setGenericUniformBufferBinding(Buffer *buffer)
+void State::setGenericUniformBufferBinding(const Context *context, Buffer *buffer)
 {
-    mGenericUniformBuffer.set(buffer);
+    mGenericUniformBuffer.set(context, buffer);
 }
 
-void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size)
+void State::setIndexedUniformBufferBinding(const Context *context,
+                                           GLuint index,
+                                           Buffer *buffer,
+                                           GLintptr offset,
+                                           GLsizeiptr size)
 {
-    mUniformBuffers[index].set(buffer, offset, size);
+    mUniformBuffers[index].set(context, buffer, offset, size);
 }
 
 const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index) const
@@ -1181,18 +1189,19 @@
     return mUniformBuffers[index];
 }
 
-void State::setGenericAtomicCounterBufferBinding(Buffer *buffer)
+void State::setGenericAtomicCounterBufferBinding(const Context *context, Buffer *buffer)
 {
-    mGenericAtomicCounterBuffer.set(buffer);
+    mGenericAtomicCounterBuffer.set(context, buffer);
 }
 
-void State::setIndexedAtomicCounterBufferBinding(GLuint index,
+void State::setIndexedAtomicCounterBufferBinding(const Context *context,
+                                                 GLuint index,
                                                  Buffer *buffer,
                                                  GLintptr offset,
                                                  GLsizeiptr size)
 {
     ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
-    mAtomicCounterBuffers[index].set(buffer, offset, size);
+    mAtomicCounterBuffers[index].set(context, buffer, offset, size);
 }
 
 const OffsetBindingPointer<Buffer> &State::getIndexedAtomicCounterBuffer(size_t index) const
@@ -1201,18 +1210,19 @@
     return mAtomicCounterBuffers[index];
 }
 
-void State::setGenericShaderStorageBufferBinding(Buffer *buffer)
+void State::setGenericShaderStorageBufferBinding(const Context *context, Buffer *buffer)
 {
-    mGenericShaderStorageBuffer.set(buffer);
+    mGenericShaderStorageBuffer.set(context, buffer);
 }
 
-void State::setIndexedShaderStorageBufferBinding(GLuint index,
+void State::setIndexedShaderStorageBufferBinding(const Context *context,
+                                                 GLuint index,
                                                  Buffer *buffer,
                                                  GLintptr offset,
                                                  GLsizeiptr size)
 {
     ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
-    mShaderStorageBuffers[index].set(buffer, offset, size);
+    mShaderStorageBuffers[index].set(context, buffer, offset, size);
 }
 
 const OffsetBindingPointer<Buffer> &State::getIndexedShaderStorageBuffer(size_t index) const
@@ -1221,25 +1231,25 @@
     return mShaderStorageBuffers[index];
 }
 
-void State::setCopyReadBufferBinding(Buffer *buffer)
+void State::setCopyReadBufferBinding(const Context *context, Buffer *buffer)
 {
-    mCopyReadBuffer.set(buffer);
+    mCopyReadBuffer.set(context, buffer);
 }
 
-void State::setCopyWriteBufferBinding(Buffer *buffer)
+void State::setCopyWriteBufferBinding(const Context *context, Buffer *buffer)
 {
-    mCopyWriteBuffer.set(buffer);
+    mCopyWriteBuffer.set(context, buffer);
 }
 
-void State::setPixelPackBufferBinding(Buffer *buffer)
+void State::setPixelPackBufferBinding(const Context *context, Buffer *buffer)
 {
-    mPack.pixelBuffer.set(buffer);
+    mPack.pixelBuffer.set(context, buffer);
     mDirtyBits.set(DIRTY_BIT_PACK_BUFFER_BINDING);
 }
 
-void State::setPixelUnpackBufferBinding(Buffer *buffer)
+void State::setPixelUnpackBufferBinding(const Context *context, Buffer *buffer)
 {
-    mUnpack.pixelBuffer.set(buffer);
+    mUnpack.pixelBuffer.set(context, buffer);
     mDirtyBits.set(DIRTY_BIT_UNPACK_BUFFER_BINDING);
 }
 
@@ -1267,7 +1277,7 @@
     }
 }
 
-void State::detachBuffer(GLuint bufferName)
+void State::detachBuffer(const Context *context, GLuint bufferName)
 {
     BindingPointer<Buffer> *buffers[] = {
         &mArrayBuffer,        &mGenericAtomicCounterBuffer, &mCopyReadBuffer,
@@ -1277,17 +1287,17 @@
     {
         if (buffer->id() == bufferName)
         {
-            buffer->set(nullptr);
+            buffer->set(context, nullptr);
         }
     }
 
     TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
     if (curTransformFeedback)
     {
-        curTransformFeedback->detachBuffer(bufferName);
+        curTransformFeedback->detachBuffer(context, bufferName);
     }
 
-    getVertexArray()->detachBuffer(bufferName);
+    getVertexArray()->detachBuffer(context, bufferName);
 }
 
 void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
@@ -1317,7 +1327,8 @@
     mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index);
 }
 
-void State::setVertexAttribState(unsigned int attribNum,
+void State::setVertexAttribState(const Context *context,
+                                 unsigned int attribNum,
                                  Buffer *boundBuffer,
                                  GLint size,
                                  GLenum type,
@@ -1326,7 +1337,8 @@
                                  GLsizei stride,
                                  const void *pointer)
 {
-    getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer);
+    getVertexArray()->setAttributeState(context, attribNum, boundBuffer, size, type, normalized,
+                                        pureInteger, stride, pointer);
     mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
 }
 
@@ -1759,8 +1771,12 @@
       case GL_STENCIL_WRITEMASK:                        *params = clampToInt(mDepthStencil.stencilWritemask);     break;
       case GL_STENCIL_BACK_WRITEMASK:                   *params = clampToInt(mDepthStencil.stencilBackWritemask); break;
       case GL_STENCIL_CLEAR_VALUE:                      *params = mStencilClearValue;                             break;
-      case GL_IMPLEMENTATION_COLOR_READ_TYPE:           *params = mReadFramebuffer->getImplementationColorReadType();   break;
-      case GL_IMPLEMENTATION_COLOR_READ_FORMAT:         *params = mReadFramebuffer->getImplementationColorReadFormat(); break;
+      case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+          *params = mReadFramebuffer->getImplementationColorReadType(context);
+          break;
+      case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+          *params = mReadFramebuffer->getImplementationColorReadFormat(context);
+          break;
       case GL_SAMPLE_BUFFERS:
       case GL_SAMPLES:
         {
diff --git a/src/libANGLE/State.h b/src/libANGLE/State.h
index f6a018d..ecb5095 100644
--- a/src/libANGLE/State.h
+++ b/src/libANGLE/State.h
@@ -41,9 +41,7 @@
     State();
     ~State();
 
-    void initialize(const Caps &caps,
-                    const Extensions &extensions,
-                    const Version &clientVersion,
+    void initialize(const Context *context,
                     bool debug,
                     bool bindGeneratesResource,
                     bool clientArraysEnabled,
@@ -169,21 +167,21 @@
     // Texture binding & active texture unit manipulation
     void setActiveSampler(unsigned int active);
     unsigned int getActiveSampler() const;
-    void setSamplerTexture(GLenum type, Texture *texture);
+    void setSamplerTexture(const Context *context, GLenum type, Texture *texture);
     Texture *getTargetTexture(GLenum target) const;
     Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
     GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const;
     void detachTexture(const Context *context, const TextureMap &zeroTextures, GLuint texture);
-    void initializeZeroTextures(const TextureMap &zeroTextures);
+    void initializeZeroTextures(const Context *context, const TextureMap &zeroTextures);
 
     // Sampler object binding manipulation
-    void setSamplerBinding(GLuint textureUnit, Sampler *sampler);
+    void setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler);
     GLuint getSamplerId(GLuint textureUnit) const;
     Sampler *getSampler(GLuint textureUnit) const;
-    void detachSampler(GLuint sampler);
+    void detachSampler(const Context *context, GLuint sampler);
 
     // Renderbuffer binding manipulation
-    void setRenderbufferBinding(Renderbuffer *renderbuffer);
+    void setRenderbufferBinding(const Context *context, Renderbuffer *renderbuffer);
     GLuint getRenderbufferId() const;
     Renderbuffer *getCurrentRenderbuffer() const;
     void detachRenderbuffer(const Context *context, GLuint renderbuffer);
@@ -208,70 +206,74 @@
     Program *getProgram() const;
 
     // Transform feedback object (not buffer) binding manipulation
-    void setTransformFeedbackBinding(TransformFeedback *transformFeedback);
+    void setTransformFeedbackBinding(const Context *context, TransformFeedback *transformFeedback);
     TransformFeedback *getCurrentTransformFeedback() const;
     bool isTransformFeedbackActiveUnpaused() const;
-    bool removeTransformFeedbackBinding(GLuint transformFeedback);
+    bool removeTransformFeedbackBinding(const Context *context, GLuint transformFeedback);
 
     // Query binding manipulation
     bool isQueryActive(const GLenum type) const;
     bool isQueryActive(Query *query) const;
-    void setActiveQuery(GLenum target, Query *query);
+    void setActiveQuery(const Context *context, GLenum target, Query *query);
     GLuint getActiveQueryId(GLenum target) const;
     Query *getActiveQuery(GLenum target) const;
 
     //// Typed buffer binding point manipulation ////
     // GL_ARRAY_BUFFER
-    void setArrayBufferBinding(Buffer *buffer);
+    void setArrayBufferBinding(const Context *context, Buffer *buffer);
     GLuint getArrayBufferId() const;
 
-    void setDrawIndirectBufferBinding(Buffer *buffer);
+    void setDrawIndirectBufferBinding(const Context *context, Buffer *buffer);
     Buffer *getDrawIndirectBuffer() const { return mDrawIndirectBuffer.get(); }
 
     // GL_UNIFORM_BUFFER - Both indexed and generic targets
-    void setGenericUniformBufferBinding(Buffer *buffer);
-    void setIndexedUniformBufferBinding(GLuint index,
+    void setGenericUniformBufferBinding(const Context *context, Buffer *buffer);
+    void setIndexedUniformBufferBinding(const Context *context,
+                                        GLuint index,
                                         Buffer *buffer,
                                         GLintptr offset,
                                         GLsizeiptr size);
     const OffsetBindingPointer<Buffer> &getIndexedUniformBuffer(size_t index) const;
 
     // GL_ATOMIC_COUNTER_BUFFER - Both indexed and generic targets
-    void setGenericAtomicCounterBufferBinding(Buffer *buffer);
-    void setIndexedAtomicCounterBufferBinding(GLuint index,
+    void setGenericAtomicCounterBufferBinding(const Context *context, Buffer *buffer);
+    void setIndexedAtomicCounterBufferBinding(const Context *context,
+                                              GLuint index,
                                               Buffer *buffer,
                                               GLintptr offset,
                                               GLsizeiptr size);
     const OffsetBindingPointer<Buffer> &getIndexedAtomicCounterBuffer(size_t index) const;
 
     // GL_SHADER_STORAGE_BUFFER - Both indexed and generic targets
-    void setGenericShaderStorageBufferBinding(Buffer *buffer);
-    void setIndexedShaderStorageBufferBinding(GLuint index,
+    void setGenericShaderStorageBufferBinding(const Context *context, Buffer *buffer);
+    void setIndexedShaderStorageBufferBinding(const Context *context,
+                                              GLuint index,
                                               Buffer *buffer,
                                               GLintptr offset,
                                               GLsizeiptr size);
     const OffsetBindingPointer<Buffer> &getIndexedShaderStorageBuffer(size_t index) const;
 
     // GL_COPY_[READ/WRITE]_BUFFER
-    void setCopyReadBufferBinding(Buffer *buffer);
-    void setCopyWriteBufferBinding(Buffer *buffer);
+    void setCopyReadBufferBinding(const Context *context, Buffer *buffer);
+    void setCopyWriteBufferBinding(const Context *context, Buffer *buffer);
 
     // GL_PIXEL[PACK/UNPACK]_BUFFER
-    void setPixelPackBufferBinding(Buffer *buffer);
-    void setPixelUnpackBufferBinding(Buffer *buffer);
+    void setPixelPackBufferBinding(const Context *context, Buffer *buffer);
+    void setPixelUnpackBufferBinding(const Context *context, Buffer *buffer);
 
     // Retrieve typed buffer by target (non-indexed)
     Buffer *getTargetBuffer(GLenum target) const;
     // Detach a buffer from all bindings
-    void detachBuffer(GLuint bufferName);
+    void detachBuffer(const Context *context, GLuint bufferName);
 
     // Vertex attrib manipulation
     void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);
-    void setElementArrayBuffer(Buffer *buffer);
+    void setElementArrayBuffer(const Context *context, Buffer *buffer);
     void setVertexAttribf(GLuint index, const GLfloat values[4]);
     void setVertexAttribu(GLuint index, const GLuint values[4]);
     void setVertexAttribi(GLuint index, const GLint values[4]);
-    void setVertexAttribState(unsigned int attribNum,
+    void setVertexAttribState(const Context *context,
+                              unsigned int attribNum,
                               Buffer *boundBuffer,
                               GLint size,
                               GLenum type,
@@ -282,7 +284,8 @@
     void setVertexAttribDivisor(GLuint index, GLuint divisor);
     const VertexAttribCurrentValueData &getVertexAttribCurrentValue(size_t attribNum) const;
     const void *getVertexAttribPointer(unsigned int attribNum) const;
-    void bindVertexBuffer(GLuint bindingIndex,
+    void bindVertexBuffer(const Context *context,
+                          GLuint bindingIndex,
                           Buffer *boundBuffer,
                           GLintptr offset,
                           GLsizei stride);
diff --git a/src/libANGLE/Stream.cpp b/src/libANGLE/Stream.cpp
index d979c75..94c118b 100644
--- a/src/libANGLE/Stream.cpp
+++ b/src/libANGLE/Stream.cpp
@@ -176,7 +176,7 @@
 }
 
 // Called when the consumer of this stream starts using the stream
-Error Stream::consumerAcquire()
+Error Stream::consumerAcquire(const gl::Context *context)
 {
     ASSERT(mState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR ||
            mState == EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR);
@@ -193,14 +193,14 @@
         if (mPlanes[i].texture != nullptr)
         {
             mPlanes[i].texture->acquireImageFromStream(
-                mProducerImplementation->getGLFrameDescription(i));
+                context, mProducerImplementation->getGLFrameDescription(i));
         }
     }
 
     return NoError();
 }
 
-Error Stream::consumerRelease()
+Error Stream::consumerRelease(const gl::Context *context)
 {
     ASSERT(mState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR ||
            mState == EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR);
@@ -213,7 +213,7 @@
     {
         if (mPlanes[i].texture != nullptr)
         {
-            mPlanes[i].texture->releaseImageFromStream();
+            mPlanes[i].texture->releaseImageFromStream(context);
         }
     }
 
diff --git a/src/libANGLE/Stream.h b/src/libANGLE/Stream.h
index 799e326..b674c44 100644
--- a/src/libANGLE/Stream.h
+++ b/src/libANGLE/Stream.h
@@ -33,6 +33,7 @@
 {
 class Display;
 class Error;
+class Thread;
 
 class Stream final : angle::NonCopyable
 {
@@ -87,8 +88,8 @@
     Error createProducerD3D11TextureNV12(const AttributeMap &attributes);
 
     // Consumer methods
-    Error consumerAcquire();
-    Error consumerRelease();
+    Error consumerAcquire(const gl::Context *context);
+    Error consumerRelease(const gl::Context *context);
 
     // Some consumers are bound to GL contexts. This validates that a given context is bound to the
     // stream's consumer
diff --git a/src/libANGLE/Surface.cpp b/src/libANGLE/Surface.cpp
index cc0d418..7625b3b 100644
--- a/src/libANGLE/Surface.cpp
+++ b/src/libANGLE/Surface.cpp
@@ -15,9 +15,11 @@
 #include <iostream>
 
 #include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
 #include "libANGLE/Display.h"
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/Texture.h"
+#include "libANGLE/Thread.h"
 #include "libANGLE/formatutils.h"
 #include "libANGLE/renderer/EGLImplFactory.h"
 
@@ -75,21 +77,9 @@
 
 Surface::~Surface()
 {
-    if (mTexture.get())
-    {
-        if (mImplementation)
-        {
-            mImplementation->releaseTexImage(EGL_BACK_BUFFER);
-        }
-        mTexture->releaseTexImageFromSurface();
-        mTexture.set(nullptr);
-    }
-
-    SafeDelete(mState.defaultFramebuffer);
-    SafeDelete(mImplementation);
 }
 
-void Surface::destroy(const Display *display)
+Error Surface::destroyImpl(const Display *display)
 {
     if (mState.defaultFramebuffer)
     {
@@ -99,7 +89,30 @@
     {
         mImplementation->destroy(display);
     }
+
+    if (mTexture.get())
+    {
+        if (mImplementation)
+        {
+            ANGLE_TRY(mImplementation->releaseTexImage(EGL_BACK_BUFFER));
+        }
+        auto glErr = mTexture->releaseTexImageFromSurface(display->getProxyContext());
+        if (glErr.isError())
+        {
+            return Error(EGL_BAD_SURFACE);
+        }
+        mTexture.set(nullptr, nullptr);
+    }
+
+    if (mState.defaultFramebuffer)
+    {
+        mState.defaultFramebuffer->onDestroy(display->getProxyContext());
+    }
+    SafeDelete(mState.defaultFramebuffer);
+    SafeDelete(mImplementation);
+
     delete this;
+    return NoError();
 }
 
 Error Surface::initialize(const Display *display)
@@ -111,35 +124,38 @@
     mSwapBehavior = mImplementation->getSwapBehavior();
 
     // Must happen after implementation initialize for OSX.
-    mState.defaultFramebuffer = createDefaultFramebuffer();
+    mState.defaultFramebuffer = createDefaultFramebuffer(display);
     ASSERT(mState.defaultFramebuffer != nullptr);
 
     return NoError();
 }
 
-void Surface::setIsCurrent(Display *display, bool isCurrent)
+Error Surface::setIsCurrent(const gl::Context *context, bool isCurrent)
 {
     if (isCurrent)
     {
         mCurrentCount++;
-        return;
+        return NoError();
     }
 
     ASSERT(mCurrentCount > 0);
     mCurrentCount--;
     if (mCurrentCount == 0 && mDestroyed)
     {
-        destroy(display);
+        ASSERT(context);
+        return destroyImpl(context->getCurrentDisplay());
     }
+    return NoError();
 }
 
-void Surface::onDestroy(const Display *display)
+Error Surface::onDestroy(const Display *display)
 {
     mDestroyed = true;
     if (mCurrentCount == 0)
     {
-        destroy(display);
+        return destroyImpl(display);
     }
+    return NoError();
 }
 
 EGLint Surface::getType() const
@@ -226,24 +242,34 @@
     return mFixedSize ? static_cast<EGLint>(mFixedHeight) : mImplementation->getHeight();
 }
 
-Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer)
+Error Surface::bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer)
 {
     ASSERT(!mTexture.get());
     ANGLE_TRY(mImplementation->bindTexImage(texture, buffer));
 
-    texture->bindTexImageFromSurface(this);
-    mTexture.set(texture);
+    auto glErr = texture->bindTexImageFromSurface(context, this);
+    if (glErr.isError())
+    {
+        return Error(EGL_BAD_SURFACE);
+    }
+    mTexture.set(context, texture);
 
     return NoError();
 }
 
-Error Surface::releaseTexImage(EGLint buffer)
+Error Surface::releaseTexImage(const gl::Context *context, EGLint buffer)
 {
+    ASSERT(context);
+
     ANGLE_TRY(mImplementation->releaseTexImage(buffer));
 
     ASSERT(mTexture.get());
-    mTexture->releaseTexImageFromSurface();
-    mTexture.set(nullptr);
+    auto glErr = mTexture->releaseTexImageFromSurface(context);
+    if (glErr.isError())
+    {
+        return Error(EGL_BAD_SURFACE);
+    }
+    mTexture.set(context, nullptr);
 
     return NoError();
 }
@@ -253,10 +279,10 @@
     return mImplementation->getSyncValues(ust, msc, sbc);
 }
 
-void Surface::releaseTexImageFromTexture()
+void Surface::releaseTexImageFromTexture(const gl::Context *context)
 {
     ASSERT(mTexture.get());
-    mTexture.set(nullptr);
+    mTexture.set(context, nullptr);
 }
 
 gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const
@@ -280,9 +306,9 @@
     return 0;
 }
 
-gl::Framebuffer *Surface::createDefaultFramebuffer()
+gl::Framebuffer *Surface::createDefaultFramebuffer(const Display *display)
 {
-    return new gl::Framebuffer(this);
+    return new gl::Framebuffer(display, this);
 }
 
 WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
diff --git a/src/libANGLE/Surface.h b/src/libANGLE/Surface.h
index 76ec0a5..f670caf 100644
--- a/src/libANGLE/Surface.h
+++ b/src/libANGLE/Surface.h
@@ -36,7 +36,6 @@
 class AttributeMap;
 class Display;
 struct Config;
-class Thread;
 
 struct SurfaceState final : private angle::NonCopyable
 {
@@ -62,16 +61,16 @@
                         EGLint width,
                         EGLint height);
     Error querySurfacePointerANGLE(EGLint attribute, void **value);
-    Error bindTexImage(gl::Texture *texture, EGLint buffer);
-    Error releaseTexImage(EGLint buffer);
+    Error bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer);
+    Error releaseTexImage(const gl::Context *context, EGLint buffer);
 
     Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc);
 
     EGLint isPostSubBufferSupported() const;
 
     void setSwapInterval(EGLint interval);
-    void setIsCurrent(Display *display, bool isCurrent);
-    void onDestroy(const Display *display);
+    Error setIsCurrent(const gl::Context *context, bool isCurrent);
+    Error onDestroy(const Display *display);
 
     const Config *getConfig() const;
 
@@ -95,8 +94,8 @@
                                           const gl::ImageIndex &imageIndex) const override;
     GLsizei getAttachmentSamples(const gl::ImageIndex &imageIndex) const override;
 
-    void onAttach() override {}
-    void onDetach() override {}
+    void onAttach(const gl::Context *context) override {}
+    void onDetach(const gl::Context *context) override {}
     GLuint getId() const override;
 
     bool flexibleSurfaceCompatibilityRequested() const
@@ -112,11 +111,11 @@
     virtual ~Surface();
     rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mImplementation; }
 
-    gl::Framebuffer *createDefaultFramebuffer();
+    gl::Framebuffer *createDefaultFramebuffer(const Display *display);
 
     // ANGLE-only method, used internally
     friend class gl::Texture;
-    void releaseTexImageFromTexture();
+    void releaseTexImageFromTexture(const gl::Context *context);
 
     SurfaceState mState;
     rx::SurfaceImpl *mImplementation;
@@ -143,13 +142,13 @@
 
     EGLint mOrientation;
 
-    BindingPointer<gl::Texture> mTexture;
+    gl::BindingPointer<gl::Texture> mTexture;
 
     gl::Format mBackFormat;
     gl::Format mDSFormat;
 
   private:
-    void destroy(const egl::Display *display);
+    Error destroyImpl(const Display *display);
 };
 
 class WindowSurface final : public Surface
diff --git a/src/libANGLE/Surface_unittest.cpp b/src/libANGLE/Surface_unittest.cpp
index d95540e..6356a82 100644
--- a/src/libANGLE/Surface_unittest.cpp
+++ b/src/libANGLE/Surface_unittest.cpp
@@ -43,8 +43,9 @@
     MOCK_CONST_METHOD0(getHeight, EGLint());
     MOCK_CONST_METHOD0(isPostSubBufferSupported, EGLint(void));
     MOCK_CONST_METHOD0(getSwapBehavior, EGLint(void));
-    MOCK_METHOD3(getAttachmentRenderTarget,
-                 gl::Error(GLenum,
+    MOCK_METHOD4(getAttachmentRenderTarget,
+                 gl::Error(const gl::Context *,
+                           GLenum,
                            const gl::ImageIndex &,
                            rx::FramebufferAttachmentRenderTarget **));
 
diff --git a/src/libANGLE/Texture.cpp b/src/libANGLE/Texture.cpp
index e4b7203..ddbb5d4 100644
--- a/src/libANGLE/Texture.cpp
+++ b/src/libANGLE/Texture.cpp
@@ -528,11 +528,13 @@
 {
 }
 
-Texture::~Texture()
+void Texture::onDestroy(const Context *context)
 {
     if (mBoundSurface)
     {
-        mBoundSurface->releaseTexImage(EGL_BACK_BUFFER);
+        auto eglErr = mBoundSurface->releaseTexImage(context, EGL_BACK_BUFFER);
+        // TODO(jmadill): handle error.
+        ASSERT(!eglErr.isError());
         mBoundSurface = nullptr;
     }
     if (mBoundStream)
@@ -540,7 +542,22 @@
         mBoundStream->releaseTextures();
         mBoundStream = nullptr;
     }
-    SafeDelete(mTexture);
+
+    auto err = orphanImages(context);
+    // TODO(jmadill): handle error.
+    ASSERT(!err.isError());
+
+    if (mTexture)
+    {
+        err = mTexture->onDestroy(context);
+        // TODO(jmadill): handle error.
+        ASSERT(!err.isError());
+        SafeDelete(mTexture);
+    }
+}
+
+Texture::~Texture()
+{
 }
 
 void Texture::setLabel(const std::string &label)
@@ -729,13 +746,15 @@
     return mState.mSamplerState;
 }
 
-void Texture::setBaseLevel(GLuint baseLevel)
+Error Texture::setBaseLevel(const Context *context, GLuint baseLevel)
 {
     if (mState.setBaseLevel(baseLevel))
     {
-        mTexture->setBaseLevel(mState.getEffectiveBaseLevel());
+        ANGLE_TRY(mTexture->setBaseLevel(context, mState.getEffectiveBaseLevel()));
         mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
     }
+
+    return NoError();
 }
 
 GLuint Texture::getBaseLevel() const
@@ -879,8 +898,8 @@
            (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
 
     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
-    releaseTexImageInternal();
-    orphanImages();
+    ANGLE_TRY(releaseTexImageInternal(context));
+    ANGLE_TRY(orphanImages(context));
 
     ANGLE_TRY(mTexture->setImage(context, target, level, internalFormat, size, format, type,
                                  unpackState, pixels));
@@ -918,8 +937,8 @@
            (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
 
     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
-    releaseTexImageInternal();
-    orphanImages();
+    ANGLE_TRY(releaseTexImageInternal(context));
+    ANGLE_TRY(orphanImages(context));
 
     ANGLE_TRY(mTexture->setCompressedImage(context, target, level, internalFormat, size,
                                            unpackState, imageSize, pixels));
@@ -957,8 +976,8 @@
            (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
 
     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
-    releaseTexImageInternal();
-    orphanImages();
+    ANGLE_TRY(releaseTexImageInternal(context));
+    ANGLE_TRY(orphanImages(context));
 
     ANGLE_TRY(mTexture->copyImage(context, target, level, sourceArea, internalFormat, source));
 
@@ -999,8 +1018,8 @@
            (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
 
     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
-    releaseTexImageInternal();
-    orphanImages();
+    ANGLE_TRY(releaseTexImageInternal(context));
+    ANGLE_TRY(orphanImages(context));
 
     ANGLE_TRY(mTexture->copyTexture(context, target, level, internalFormat, type, sourceLevel,
                                     unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
@@ -1036,8 +1055,8 @@
 Error Texture::copyCompressedTexture(const Context *context, const Texture *source)
 {
     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
-    releaseTexImageInternal();
-    orphanImages();
+    ANGLE_TRY(releaseTexImageInternal(context));
+    ANGLE_TRY(orphanImages(context));
 
     ANGLE_TRY(mTexture->copyCompressedTexture(context, source));
 
@@ -1057,8 +1076,8 @@
     ASSERT(target == mState.mTarget);
 
     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
-    releaseTexImageInternal();
-    orphanImages();
+    ANGLE_TRY(releaseTexImageInternal(context));
+    ANGLE_TRY(orphanImages(context));
 
     ANGLE_TRY(mTexture->setStorage(context, target, levels, internalFormat, size));
 
@@ -1089,8 +1108,8 @@
     ASSERT(target == mState.mTarget);
 
     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
-    releaseTexImageInternal();
-    orphanImages();
+    ANGLE_TRY(releaseTexImageInternal(context));
+    ANGLE_TRY(orphanImages(context));
 
     ANGLE_TRY(mTexture->setStorageMultisample(context, target, samples, internalFormat, size,
                                               fixedSampleLocations));
@@ -1109,13 +1128,13 @@
 Error Texture::generateMipmap(const Context *context)
 {
     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
-    releaseTexImageInternal();
+    ANGLE_TRY(releaseTexImageInternal(context));
 
     // EGL_KHR_gl_image states that images are only orphaned when generating mipmaps if the texture
     // is not mip complete.
     if (!isMipmapComplete())
     {
-        orphanImages();
+        ANGLE_TRY(orphanImages(context));
     }
 
     const GLuint baseLevel = mState.getEffectiveBaseLevel();
@@ -1136,16 +1155,16 @@
     return NoError();
 }
 
-void Texture::bindTexImageFromSurface(egl::Surface *surface)
+Error Texture::bindTexImageFromSurface(const Context *context, egl::Surface *surface)
 {
     ASSERT(surface);
 
     if (mBoundSurface)
     {
-        releaseTexImageFromSurface();
+        ANGLE_TRY(releaseTexImageFromSurface(context));
     }
 
-    mTexture->bindTexImage(surface);
+    ANGLE_TRY(mTexture->bindTexImage(context, surface));
     mBoundSurface = surface;
 
     // Set the image info to the size and format of the surface
@@ -1154,18 +1173,20 @@
     ImageDesc desc(size, Format(surface->getConfig()->renderTargetFormat));
     mState.setImageDesc(mState.mTarget, 0, desc);
     mDirtyChannel.signal();
+    return NoError();
 }
 
-void Texture::releaseTexImageFromSurface()
+Error Texture::releaseTexImageFromSurface(const Context *context)
 {
     ASSERT(mBoundSurface);
     mBoundSurface = nullptr;
-    mTexture->releaseTexImage();
+    ANGLE_TRY(mTexture->releaseTexImage(context));
 
     // Erase the image info for level 0
     ASSERT(mState.mTarget == GL_TEXTURE_2D);
     mState.clearImageDesc(mState.mTarget, 0);
     mDirtyChannel.signal();
+    return NoError();
 }
 
 void Texture::bindStream(egl::Stream *stream)
@@ -1186,50 +1207,55 @@
     mBoundStream = nullptr;
 }
 
-void Texture::acquireImageFromStream(const egl::Stream::GLTextureDescription &desc)
+Error Texture::acquireImageFromStream(const Context *context,
+                                      const egl::Stream::GLTextureDescription &desc)
 {
     ASSERT(mBoundStream != nullptr);
-    mTexture->setImageExternal(mState.mTarget, mBoundStream, desc);
+    ANGLE_TRY(mTexture->setImageExternal(context, mState.mTarget, mBoundStream, desc));
 
     Extents size(desc.width, desc.height, 1);
     mState.setImageDesc(mState.mTarget, 0, ImageDesc(size, Format(desc.internalFormat)));
     mDirtyChannel.signal();
+    return NoError();
 }
 
-void Texture::releaseImageFromStream()
+Error Texture::releaseImageFromStream(const Context *context)
 {
     ASSERT(mBoundStream != nullptr);
-    mTexture->setImageExternal(mState.mTarget, nullptr, egl::Stream::GLTextureDescription());
+    ANGLE_TRY(mTexture->setImageExternal(context, mState.mTarget, nullptr,
+                                         egl::Stream::GLTextureDescription()));
 
     // Set to incomplete
     mState.clearImageDesc(mState.mTarget, 0);
     mDirtyChannel.signal();
+    return NoError();
 }
 
-void Texture::releaseTexImageInternal()
+Error Texture::releaseTexImageInternal(const Context *context)
 {
     if (mBoundSurface)
     {
         // Notify the surface
-        mBoundSurface->releaseTexImageFromTexture();
+        mBoundSurface->releaseTexImageFromTexture(context);
 
         // Then, call the same method as from the surface
-        releaseTexImageFromSurface();
+        ANGLE_TRY(releaseTexImageFromSurface(context));
     }
+    return NoError();
 }
 
-Error Texture::setEGLImageTarget(GLenum target, egl::Image *imageTarget)
+Error Texture::setEGLImageTarget(const Context *context, GLenum target, egl::Image *imageTarget)
 {
     ASSERT(target == mState.mTarget);
     ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES);
 
     // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
-    releaseTexImageInternal();
-    orphanImages();
+    ANGLE_TRY(releaseTexImageInternal(context));
+    ANGLE_TRY(orphanImages(context));
 
-    ANGLE_TRY(mTexture->setEGLImageTarget(target, imageTarget));
+    ANGLE_TRY(mTexture->setEGLImageTarget(context, target, imageTarget));
 
-    setTargetImage(imageTarget);
+    setTargetImage(context, imageTarget);
 
     Extents size(static_cast<int>(imageTarget->getWidth()),
                  static_cast<int>(imageTarget->getHeight()), 1);
@@ -1256,14 +1282,14 @@
     return getSamples(imageIndex.type, 0);
 }
 
-void Texture::onAttach()
+void Texture::onAttach(const Context *context)
 {
     addRef();
 }
 
-void Texture::onDetach()
+void Texture::onDetach(const Context *context)
 {
-    release();
+    release(context);
 }
 
 GLuint Texture::getId() const
diff --git a/src/libANGLE/Texture.h b/src/libANGLE/Texture.h
index 7b1ad5e..13c755a 100644
--- a/src/libANGLE/Texture.h
+++ b/src/libANGLE/Texture.h
@@ -181,7 +181,7 @@
     Texture(rx::GLImplFactory *factory, GLuint id, GLenum target);
     ~Texture() override;
 
-    void destroy(const Context *context) override {}
+    void onDestroy(const Context *context) override;
 
     void setLabel(const std::string &label) override;
     const std::string &getLabel() const override;
@@ -235,7 +235,7 @@
 
     const SamplerState &getSamplerState() const;
 
-    void setBaseLevel(GLuint baseLevel);
+    gl::Error setBaseLevel(const Context *context, GLuint baseLevel);
     GLuint getBaseLevel() const;
 
     void setMaxLevel(GLuint maxLevel);
@@ -348,7 +348,7 @@
                                 const Extents &size,
                                 GLboolean fixedSampleLocations);
 
-    Error setEGLImageTarget(GLenum target, egl::Image *imageTarget);
+    Error setEGLImageTarget(const Context *context, GLenum target, egl::Image *imageTarget);
 
     Error generateMipmap(const Context *context);
 
@@ -364,8 +364,8 @@
     const Format &getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const override;
     GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const override;
 
-    void onAttach() override;
-    void onDetach() override;
+    void onAttach(const Context *context) override;
+    void onDetach(const Context *context) override;
     GLuint getId() const override;
 
     enum DirtyBitType
@@ -407,15 +407,16 @@
 
     // ANGLE-only method, used internally
     friend class egl::Surface;
-    void bindTexImageFromSurface(egl::Surface *surface);
-    void releaseTexImageFromSurface();
+    Error bindTexImageFromSurface(const Context *context, egl::Surface *surface);
+    Error releaseTexImageFromSurface(const Context *context);
 
     // ANGLE-only methods, used internally
     friend class egl::Stream;
     void bindStream(egl::Stream *stream);
     void releaseStream();
-    void acquireImageFromStream(const egl::Stream::GLTextureDescription &desc);
-    void releaseImageFromStream();
+    Error acquireImageFromStream(const Context *context,
+                                 const egl::Stream::GLTextureDescription &desc);
+    Error releaseImageFromStream(const Context *context);
 
     TextureState mState;
     DirtyBits mDirtyBits;
@@ -423,7 +424,7 @@
 
     std::string mLabel;
 
-    void releaseTexImageInternal();
+    Error releaseTexImageInternal(const Context *context);
 
     egl::Surface *mBoundSurface;
     egl::Stream *mBoundStream;
diff --git a/src/libANGLE/TransformFeedback.cpp b/src/libANGLE/TransformFeedback.cpp
index 70a12cd..5025480 100644
--- a/src/libANGLE/TransformFeedback.cpp
+++ b/src/libANGLE/TransformFeedback.cpp
@@ -50,25 +50,26 @@
     ASSERT(mImplementation != nullptr);
 }
 
-void TransformFeedback::destroy(const Context *context)
+void TransformFeedback::onDestroy(const Context *context)
 {
     if (mState.mProgram)
     {
         mState.mProgram->release(context);
         mState.mProgram = nullptr;
     }
+
+    ASSERT(!mState.mProgram);
+    mState.mGenericBuffer.set(context, nullptr);
+    for (size_t i = 0; i < mState.mIndexedBuffers.size(); i++)
+    {
+        mState.mIndexedBuffers[i].set(context, nullptr);
+    }
+
+    SafeDelete(mImplementation);
 }
 
 TransformFeedback::~TransformFeedback()
 {
-    ASSERT(!mState.mProgram);
-    mState.mGenericBuffer.set(nullptr);
-    for (size_t i = 0; i < mState.mIndexedBuffers.size(); i++)
-    {
-        mState.mIndexedBuffers[i].set(nullptr);
-    }
-
-    SafeDelete(mImplementation);
 }
 
 void TransformFeedback::setLabel(const std::string &label)
@@ -151,26 +152,26 @@
     return mState.mProgram != nullptr && mState.mProgram->id() == program;
 }
 
-void TransformFeedback::bindGenericBuffer(Buffer *buffer)
+void TransformFeedback::bindGenericBuffer(const Context *context, Buffer *buffer)
 {
-    mState.mGenericBuffer.set(buffer);
+    mState.mGenericBuffer.set(context, buffer);
     mImplementation->bindGenericBuffer(mState.mGenericBuffer);
 }
 
-void TransformFeedback::detachBuffer(GLuint bufferName)
+void TransformFeedback::detachBuffer(const Context *context, GLuint bufferName)
 {
     for (size_t index = 0; index < mState.mIndexedBuffers.size(); index++)
     {
         if (mState.mIndexedBuffers[index].id() == bufferName)
         {
-            mState.mIndexedBuffers[index].set(nullptr);
+            mState.mIndexedBuffers[index].set(context, nullptr);
             mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]);
         }
     }
 
     if (mState.mGenericBuffer.id() == bufferName)
     {
-        mState.mGenericBuffer.set(nullptr);
+        mState.mGenericBuffer.set(context, nullptr);
         mImplementation->bindGenericBuffer(mState.mGenericBuffer);
     }
 }
@@ -180,10 +181,14 @@
     return mState.mGenericBuffer;
 }
 
-void TransformFeedback::bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size)
+void TransformFeedback::bindIndexedBuffer(const Context *context,
+                                          size_t index,
+                                          Buffer *buffer,
+                                          size_t offset,
+                                          size_t size)
 {
     ASSERT(index < mState.mIndexedBuffers.size());
-    mState.mIndexedBuffers[index].set(buffer, offset, size);
+    mState.mIndexedBuffers[index].set(context, buffer, offset, size);
     mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]);
 }
 
diff --git a/src/libANGLE/TransformFeedback.h b/src/libANGLE/TransformFeedback.h
index 2c0faff..a81d42b 100644
--- a/src/libANGLE/TransformFeedback.h
+++ b/src/libANGLE/TransformFeedback.h
@@ -56,7 +56,7 @@
   public:
     TransformFeedback(rx::GLImplFactory *implFactory, GLuint id, const Caps &caps);
     virtual ~TransformFeedback();
-    void destroy(const Context *context) override;
+    void onDestroy(const Context *context) override;
 
     void setLabel(const std::string &label) override;
     const std::string &getLabel() const override;
@@ -72,14 +72,18 @@
 
     bool hasBoundProgram(GLuint program) const;
 
-    void bindGenericBuffer(Buffer *buffer);
+    void bindGenericBuffer(const Context *context, Buffer *buffer);
     const BindingPointer<Buffer> &getGenericBuffer() const;
 
-    void bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size);
+    void bindIndexedBuffer(const Context *context,
+                           size_t index,
+                           Buffer *buffer,
+                           size_t offset,
+                           size_t size);
     const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t index) const;
     size_t getIndexedBufferCount() const;
 
-    void detachBuffer(GLuint bufferName);
+    void detachBuffer(const Context *context, GLuint bufferName);
 
     rx::TransformFeedbackImpl *getImplementation();
     const rx::TransformFeedbackImpl *getImplementation() const;
diff --git a/src/libANGLE/TransformFeedback_unittest.cpp b/src/libANGLE/TransformFeedback_unittest.cpp
index 946db6b..d019cb7 100644
--- a/src/libANGLE/TransformFeedback_unittest.cpp
+++ b/src/libANGLE/TransformFeedback_unittest.cpp
@@ -51,7 +51,7 @@
     {
         if (mFeedback)
         {
-            mFeedback->release();
+            mFeedback->release(nullptr);
         }
 
         // Only needed because the mock is leaked if bugs are present,
@@ -116,11 +116,11 @@
     EXPECT_EQ(mFeedback->getIndexedBufferCount(), mCaps.maxTransformFeedbackSeparateAttributes);
 
     EXPECT_CALL(*mImpl, bindGenericBuffer(_));
-    mFeedback->bindGenericBuffer(buffer);
+    mFeedback->bindGenericBuffer(nullptr, buffer);
     EXPECT_EQ(mFeedback->getGenericBuffer().get(), buffer);
 
     EXPECT_CALL(*mImpl, bindIndexedBuffer(_, _));
-    mFeedback->bindIndexedBuffer(bindIndex, buffer, 0, 1);
+    mFeedback->bindIndexedBuffer(nullptr, bindIndex, buffer, 0, 1);
     for (size_t i = 0; i < mFeedback->getIndexedBufferCount(); i++)
     {
         if (i == bindIndex)
@@ -137,7 +137,7 @@
     const size_t releaseCount = mFeedback->getRefCount();
     for (size_t count = 0; count < releaseCount; ++count)
     {
-        mFeedback->release();
+        mFeedback->release(nullptr);
     }
 
     mFeedback = nullptr;
diff --git a/src/libANGLE/VertexArray.cpp b/src/libANGLE/VertexArray.cpp
index 2ee0581..04b5aa3 100644
--- a/src/libANGLE/VertexArray.cpp
+++ b/src/libANGLE/VertexArray.cpp
@@ -28,11 +28,6 @@
 
 VertexArrayState::~VertexArrayState()
 {
-    for (auto &binding : mVertexBindings)
-    {
-        binding.setBuffer(nullptr);
-    }
-    mElementArrayBuffer.set(nullptr);
 }
 
 VertexArray::VertexArray(rx::GLImplFactory *factory,
@@ -45,9 +40,21 @@
 {
 }
 
+void VertexArray::onDestroy(const Context *context)
+{
+    for (auto &binding : mState.mVertexBindings)
+    {
+        binding.setBuffer(context, nullptr);
+    }
+    mState.mElementArrayBuffer.set(context, nullptr);
+    mVertexArray->destroy(context);
+    SafeDelete(mVertexArray);
+    delete this;
+}
+
 VertexArray::~VertexArray()
 {
-    SafeDelete(mVertexArray);
+    ASSERT(!mVertexArray);
 }
 
 GLuint VertexArray::id() const
@@ -65,19 +72,19 @@
     return mState.mLabel;
 }
 
-void VertexArray::detachBuffer(GLuint bufferName)
+void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
 {
     for (auto &binding : mState.mVertexBindings)
     {
         if (binding.getBuffer().id() == bufferName)
         {
-            binding.setBuffer(nullptr);
+            binding.setBuffer(context, nullptr);
         }
     }
 
     if (mState.mElementArrayBuffer.id() == bufferName)
     {
-        mState.mElementArrayBuffer.set(nullptr);
+        mState.mElementArrayBuffer.set(context, nullptr);
     }
 }
 
@@ -101,7 +108,8 @@
     return (dirtyBit - DIRTY_BIT_ATTRIB_0_ENABLED) % gl::MAX_VERTEX_ATTRIBS;
 }
 
-void VertexArray::bindVertexBuffer(size_t bindingIndex,
+void VertexArray::bindVertexBuffer(const Context *context,
+                                   size_t bindingIndex,
                                    Buffer *boundBuffer,
                                    GLintptr offset,
                                    GLsizei stride)
@@ -110,7 +118,7 @@
 
     VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
 
-    binding->setBuffer(boundBuffer);
+    binding->setBuffer(context, boundBuffer);
     binding->setOffset(offset);
     binding->setStride(stride);
     mDirtyBits.set(DIRTY_BIT_BINDING_0_BUFFER + bindingIndex);
@@ -181,7 +189,8 @@
     }
 }
 
-void VertexArray::setAttributeState(size_t attribIndex,
+void VertexArray::setAttributeState(const Context *context,
+                                    size_t attribIndex,
                                     gl::Buffer *boundBuffer,
                                     GLint size,
                                     GLenum type,
@@ -203,14 +212,14 @@
     attrib.pointer                 = pointer;
     attrib.vertexAttribArrayStride = stride;
 
-    bindVertexBuffer(attribIndex, boundBuffer, offset, effectiveStride);
+    bindVertexBuffer(context, attribIndex, boundBuffer, offset, effectiveStride);
 
     mDirtyBits.set(DIRTY_BIT_ATTRIB_0_POINTER + attribIndex);
 }
 
-void VertexArray::setElementArrayBuffer(Buffer *buffer)
+void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
 {
-    mState.mElementArrayBuffer.set(buffer);
+    mState.mElementArrayBuffer.set(context, buffer);
     mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
 }
 
diff --git a/src/libANGLE/VertexArray.h b/src/libANGLE/VertexArray.h
index 107b4fa..53b2c56 100644
--- a/src/libANGLE/VertexArray.h
+++ b/src/libANGLE/VertexArray.h
@@ -75,7 +75,8 @@
 {
   public:
     VertexArray(rx::GLImplFactory *factory, GLuint id, size_t maxAttribs, size_t maxAttribBindings);
-    ~VertexArray();
+
+    void onDestroy(const Context *context);
 
     GLuint id() const;
 
@@ -89,10 +90,11 @@
         return mState.getBindingFromAttribIndex(attribIndex);
     }
 
-    void detachBuffer(GLuint bufferName);
+    void detachBuffer(const Context *context, GLuint bufferName);
     void setVertexAttribDivisor(size_t index, GLuint divisor);
     void enableAttribute(size_t attribIndex, bool enabledState);
-    void setAttributeState(size_t attribIndex,
+    void setAttributeState(const Context *context,
+                           size_t attribIndex,
                            Buffer *boundBuffer,
                            GLint size,
                            GLenum type,
@@ -106,14 +108,15 @@
                                bool normalized,
                                bool pureInteger,
                                GLintptr relativeOffset);
-    void bindVertexBuffer(size_t bindingIndex,
+    void bindVertexBuffer(const Context *context,
+                          size_t bindingIndex,
                           Buffer *boundBuffer,
                           GLintptr offset,
                           GLsizei stride);
     void setVertexAttribBinding(size_t attribIndex, size_t bindingIndex);
     void setVertexBindingDivisor(size_t bindingIndex, GLuint divisor);
 
-    void setElementArrayBuffer(Buffer *buffer);
+    void setElementArrayBuffer(const Context *context, Buffer *buffer);
 
     const BindingPointer<Buffer> &getElementArrayBuffer() const
     {
@@ -176,6 +179,8 @@
     bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
 
   private:
+    ~VertexArray();
+
     GLuint mId;
 
     VertexArrayState mState;
diff --git a/src/libANGLE/VertexAttribute.cpp b/src/libANGLE/VertexAttribute.cpp
index 059b19d..086e64c 100644
--- a/src/libANGLE/VertexAttribute.cpp
+++ b/src/libANGLE/VertexAttribute.cpp
@@ -29,9 +29,7 @@
         mStride  = binding.mStride;
         mDivisor = binding.mDivisor;
         mOffset  = binding.mOffset;
-        mBuffer  = binding.mBuffer;
-
-        binding.setBuffer(nullptr);
+        std::swap(binding.mBuffer, mBuffer);
     }
     return *this;
 }
diff --git a/src/libANGLE/VertexAttribute.h b/src/libANGLE/VertexAttribute.h
index f1ec450..c8b8d41 100644
--- a/src/libANGLE/VertexAttribute.h
+++ b/src/libANGLE/VertexAttribute.h
@@ -36,7 +36,7 @@
     void setOffset(GLintptr offsetIn) { mOffset = offsetIn; }
 
     const BindingPointer<Buffer> &getBuffer() const { return mBuffer; }
-    void setBuffer(Buffer *bufferIn) { mBuffer.set(bufferIn); }
+    void setBuffer(const gl::Context *context, Buffer *bufferIn) { mBuffer.set(context, bufferIn); }
 
   private:
     GLuint mStride;
diff --git a/src/libANGLE/angletypes.h b/src/libANGLE/angletypes.h
index c5003f0..6c3c623 100644
--- a/src/libANGLE/angletypes.h
+++ b/src/libANGLE/angletypes.h
@@ -237,7 +237,7 @@
 static_assert(sizeof(DrawElementsIndirectCommand) == 20,
               "Unexpected size of DrawElementsIndirectCommand");
 
-struct PixelStoreStateBase
+struct PixelStoreStateBase : private angle::NonCopyable
 {
     BindingPointer<Buffer> pixelBuffer;
     GLint alignment   = 4;
@@ -246,6 +246,18 @@
     GLint skipPixels  = 0;
     GLint imageHeight = 0;
     GLint skipImages  = 0;
+
+  protected:
+    void copyFrom(const Context *context, const PixelStoreStateBase &other)
+    {
+        pixelBuffer.set(context, other.pixelBuffer.get());
+        alignment   = other.alignment;
+        rowLength   = other.rowLength;
+        skipRows    = other.skipRows;
+        skipPixels  = other.skipPixels;
+        imageHeight = other.imageHeight;
+        skipImages  = other.skipImages;
+    }
 };
 
 struct PixelUnpackState : PixelStoreStateBase
@@ -257,6 +269,11 @@
         alignment = alignmentIn;
         rowLength = rowLengthIn;
     }
+
+    void copyFrom(const Context *context, const PixelUnpackState &other)
+    {
+        PixelStoreStateBase::copyFrom(context, other);
+    }
 };
 
 struct PixelPackState : PixelStoreStateBase
@@ -269,6 +286,12 @@
         alignment = alignmentIn;
     }
 
+    void copyFrom(const Context *context, const PixelPackState &other)
+    {
+        PixelStoreStateBase::copyFrom(context, other);
+        reverseRowOrder = other.reverseRowOrder;
+    }
+
     bool reverseRowOrder = false;
 };
 
diff --git a/src/libANGLE/queryutils.cpp b/src/libANGLE/queryutils.cpp
index e649ba7..3041db7 100644
--- a/src/libANGLE/queryutils.cpp
+++ b/src/libANGLE/queryutils.cpp
@@ -182,7 +182,7 @@
 }
 
 template <typename ParamType>
-void SetTexParameterBase(Texture *texture, GLenum pname, const ParamType *params)
+void SetTexParameterBase(Context *context, Texture *texture, GLenum pname, const ParamType *params)
 {
     ASSERT(texture != nullptr);
 
@@ -228,8 +228,10 @@
             texture->setSwizzleAlpha(ConvertToGLenum(params[0]));
             break;
         case GL_TEXTURE_BASE_LEVEL:
-            texture->setBaseLevel(ConvertToGLuint(params[0]));
+        {
+            context->handleError(texture->setBaseLevel(context, ConvertToGLuint(params[0])));
             break;
+        }
         case GL_TEXTURE_MAX_LEVEL:
             texture->setMaxLevel(ConvertToGLuint(params[0]));
             break;
@@ -934,24 +936,24 @@
     return NoError();
 }
 
-void SetTexParameterf(Texture *texture, GLenum pname, GLfloat param)
+void SetTexParameterf(Context *context, Texture *texture, GLenum pname, GLfloat param)
 {
-    SetTexParameterBase(texture, pname, &param);
+    SetTexParameterBase(context, texture, pname, &param);
 }
 
-void SetTexParameterfv(Texture *texture, GLenum pname, const GLfloat *params)
+void SetTexParameterfv(Context *context, Texture *texture, GLenum pname, const GLfloat *params)
 {
-    SetTexParameterBase(texture, pname, params);
+    SetTexParameterBase(context, texture, pname, params);
 }
 
-void SetTexParameteri(Texture *texture, GLenum pname, GLint param)
+void SetTexParameteri(Context *context, Texture *texture, GLenum pname, GLint param)
 {
-    SetTexParameterBase(texture, pname, &param);
+    SetTexParameterBase(context, texture, pname, &param);
 }
 
-void SetTexParameteriv(Texture *texture, GLenum pname, const GLint *params)
+void SetTexParameteriv(Context *context, Texture *texture, GLenum pname, const GLint *params)
 {
-    SetTexParameterBase(texture, pname, params);
+    SetTexParameterBase(context, texture, pname, params);
 }
 
 void SetSamplerParameterf(Sampler *sampler, GLenum pname, GLfloat param)
diff --git a/src/libANGLE/queryutils.h b/src/libANGLE/queryutils.h
index b3485db..bc5aa51 100644
--- a/src/libANGLE/queryutils.h
+++ b/src/libANGLE/queryutils.h
@@ -103,10 +103,10 @@
                   GLsizei *length,
                   GLint *values);
 
-void SetTexParameterf(Texture *texture, GLenum pname, GLfloat param);
-void SetTexParameterfv(Texture *texture, GLenum pname, const GLfloat *params);
-void SetTexParameteri(Texture *texture, GLenum pname, GLint param);
-void SetTexParameteriv(Texture *texture, GLenum pname, const GLint *params);
+void SetTexParameterf(Context *context, Texture *texture, GLenum pname, GLfloat param);
+void SetTexParameterfv(Context *context, Texture *texture, GLenum pname, const GLfloat *params);
+void SetTexParameteri(Context *context, Texture *texture, GLenum pname, GLint param);
+void SetTexParameteriv(Context *context, Texture *texture, GLenum pname, const GLint *params);
 
 void SetSamplerParameterf(Sampler *sampler, GLenum pname, GLfloat param);
 void SetSamplerParameterfv(Sampler *sampler, GLenum pname, const GLfloat *params);
diff --git a/src/libANGLE/renderer/ContextImpl.h b/src/libANGLE/renderer/ContextImpl.h
index c66c865..153317f 100644
--- a/src/libANGLE/renderer/ContextImpl.h
+++ b/src/libANGLE/renderer/ContextImpl.h
@@ -142,7 +142,7 @@
     virtual GLint64 getTimestamp() = 0;
 
     // Context switching
-    virtual void onMakeCurrent(const gl::ContextState &data) = 0;
+    virtual void onMakeCurrent(const gl::Context *context) = 0;
 
     // Native capabilities, unmodified by gl::Context.
     virtual const gl::Caps &getNativeCaps() const                  = 0;
diff --git a/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h b/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
index 0af12ec..95ea4b8 100644
--- a/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
+++ b/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
@@ -22,7 +22,8 @@
     FramebufferAttachmentObjectImpl() {}
     virtual ~FramebufferAttachmentObjectImpl() {}
 
-    virtual gl::Error getAttachmentRenderTarget(GLenum binding,
+    virtual gl::Error getAttachmentRenderTarget(const gl::Context *context,
+                                                GLenum binding,
                                                 const gl::ImageIndex &imageIndex,
                                                 FramebufferAttachmentRenderTarget **rtOut)
     {
diff --git a/src/libANGLE/renderer/FramebufferImpl.h b/src/libANGLE/renderer/FramebufferImpl.h
index c4871bd..0166489 100644
--- a/src/libANGLE/renderer/FramebufferImpl.h
+++ b/src/libANGLE/renderer/FramebufferImpl.h
@@ -34,9 +34,14 @@
     virtual void destroy(const gl::Context *context) {}
     virtual void destroyDefault(const egl::Display *display) {}
 
-    virtual gl::Error discard(size_t count, const GLenum *attachments)    = 0;
-    virtual gl::Error invalidate(size_t count, const GLenum *attachments) = 0;
-    virtual gl::Error invalidateSub(size_t count,
+    virtual gl::Error discard(const gl::Context *context,
+                              size_t count,
+                              const GLenum *attachments) = 0;
+    virtual gl::Error invalidate(const gl::Context *context,
+                                 size_t count,
+                                 const GLenum *attachments) = 0;
+    virtual gl::Error invalidateSub(const gl::Context *context,
+                                    size_t count,
                                     const GLenum *attachments,
                                     const gl::Rectangle &area) = 0;
 
@@ -59,8 +64,8 @@
                                     GLfloat depth,
                                     GLint stencil) = 0;
 
-    virtual GLenum getImplementationColorReadFormat() const = 0;
-    virtual GLenum getImplementationColorReadType() const   = 0;
+    virtual GLenum getImplementationColorReadFormat(const gl::Context *context) const = 0;
+    virtual GLenum getImplementationColorReadType(const gl::Context *context) const   = 0;
     virtual gl::Error readPixels(const gl::Context *context,
                                  const gl::Rectangle &area,
                                  GLenum format,
diff --git a/src/libANGLE/renderer/FramebufferImpl_mock.h b/src/libANGLE/renderer/FramebufferImpl_mock.h
index a773bcf..71f77c4 100644
--- a/src/libANGLE/renderer/FramebufferImpl_mock.h
+++ b/src/libANGLE/renderer/FramebufferImpl_mock.h
@@ -23,9 +23,10 @@
     MockFramebufferImpl() : rx::FramebufferImpl(gl::FramebufferState()) {}
     virtual ~MockFramebufferImpl() { destructor(); }
 
-    MOCK_METHOD2(discard, gl::Error(size_t, const GLenum *));
-    MOCK_METHOD2(invalidate, gl::Error(size_t, const GLenum *));
-    MOCK_METHOD3(invalidateSub, gl::Error(size_t, const GLenum *, const gl::Rectangle &));
+    MOCK_METHOD3(discard, gl::Error(const gl::Context *, size_t, const GLenum *));
+    MOCK_METHOD3(invalidate, gl::Error(const gl::Context *, size_t, const GLenum *));
+    MOCK_METHOD4(invalidateSub,
+                 gl::Error(const gl::Context *, size_t, const GLenum *, const gl::Rectangle &));
 
     MOCK_METHOD2(clear, gl::Error(const gl::Context *, GLbitfield));
     MOCK_METHOD4(clearBufferfv, gl::Error(const gl::Context *, GLenum, GLint, const GLfloat *));
@@ -33,8 +34,8 @@
     MOCK_METHOD4(clearBufferiv, gl::Error(const gl::Context *, GLenum, GLint, const GLint *));
     MOCK_METHOD5(clearBufferfi, gl::Error(const gl::Context *, GLenum, GLint, GLfloat, GLint));
 
-    MOCK_CONST_METHOD0(getImplementationColorReadFormat, GLenum());
-    MOCK_CONST_METHOD0(getImplementationColorReadType, GLenum());
+    MOCK_CONST_METHOD1(getImplementationColorReadFormat, GLenum(const gl::Context *));
+    MOCK_CONST_METHOD1(getImplementationColorReadType, GLenum(const gl::Context *));
     MOCK_CONST_METHOD5(
         readPixels,
         gl::Error(const gl::Context *, const gl::Rectangle &, GLenum, GLenum, void *));
diff --git a/src/libANGLE/renderer/ImageImpl.h b/src/libANGLE/renderer/ImageImpl.h
index 206df8b..79694ea 100644
--- a/src/libANGLE/renderer/ImageImpl.h
+++ b/src/libANGLE/renderer/ImageImpl.h
@@ -12,11 +12,16 @@
 #include "common/angleutils.h"
 #include "libANGLE/Error.h"
 
+namespace gl
+{
+class Context;
+}  // namespace gl
+
 namespace egl
 {
 class ImageSibling;
 struct ImageState;
-}
+}  // namespace egl
 
 namespace rx
 {
@@ -27,7 +32,7 @@
     virtual ~ImageImpl() {}
     virtual egl::Error initialize() = 0;
 
-    virtual gl::Error orphan(egl::ImageSibling *sibling) = 0;
+    virtual gl::Error orphan(const gl::Context *context, egl::ImageSibling *sibling) = 0;
 
   protected:
     const egl::ImageState &mState;
diff --git a/src/libANGLE/renderer/ImageImpl_mock.h b/src/libANGLE/renderer/ImageImpl_mock.h
index d430528..30c0cc2 100644
--- a/src/libANGLE/renderer/ImageImpl_mock.h
+++ b/src/libANGLE/renderer/ImageImpl_mock.h
@@ -26,7 +26,7 @@
     }
     virtual ~MockImageImpl() { destructor(); }
     MOCK_METHOD0(initialize, egl::Error(void));
-    MOCK_METHOD1(orphan, gl::Error(egl::ImageSibling *));
+    MOCK_METHOD2(orphan, gl::Error(const gl::Context *, egl::ImageSibling *));
     MOCK_METHOD0(destructor, void());
 };
 }  // namespace rx
diff --git a/src/libANGLE/renderer/RenderbufferImpl_mock.h b/src/libANGLE/renderer/RenderbufferImpl_mock.h
index 2448534..39e5c70 100644
--- a/src/libANGLE/renderer/RenderbufferImpl_mock.h
+++ b/src/libANGLE/renderer/RenderbufferImpl_mock.h
@@ -25,8 +25,11 @@
     MOCK_METHOD4(setStorageMultisample, gl::Error(size_t, GLenum, size_t, size_t));
     MOCK_METHOD1(setStorageEGLImageTarget, gl::Error(egl::Image *));
 
-    MOCK_METHOD3(getAttachmentRenderTarget,
-                 gl::Error(GLenum, const gl::ImageIndex &, FramebufferAttachmentRenderTarget **));
+    MOCK_METHOD4(getAttachmentRenderTarget,
+                 gl::Error(const gl::Context *,
+                           GLenum,
+                           const gl::ImageIndex &,
+                           FramebufferAttachmentRenderTarget **));
 
     MOCK_METHOD0(destructor, void());
 };
diff --git a/src/libANGLE/renderer/TextureImpl.h b/src/libANGLE/renderer/TextureImpl.h
index b814534..0412c3e 100644
--- a/src/libANGLE/renderer/TextureImpl.h
+++ b/src/libANGLE/renderer/TextureImpl.h
@@ -46,6 +46,8 @@
     TextureImpl(const gl::TextureState &state);
     virtual ~TextureImpl();
 
+    virtual gl::Error onDestroy(const gl::Context *context) { return gl::NoError(); }
+
     virtual gl::Error setImage(const gl::Context *context,
                                GLenum target,
                                size_t level,
@@ -130,18 +132,21 @@
                                             const gl::Extents &size,
                                             GLboolean fixedSampleLocations) = 0;
 
-    virtual gl::Error setEGLImageTarget(GLenum target, egl::Image *image) = 0;
+    virtual gl::Error setEGLImageTarget(const gl::Context *context,
+                                        GLenum target,
+                                        egl::Image *image) = 0;
 
-    virtual gl::Error setImageExternal(GLenum target,
+    virtual gl::Error setImageExternal(const gl::Context *context,
+                                       GLenum target,
                                        egl::Stream *stream,
                                        const egl::Stream::GLTextureDescription &desc) = 0;
 
     virtual gl::Error generateMipmap(const gl::Context *context) = 0;
 
-    virtual void setBaseLevel(GLuint baseLevel) = 0;
+    virtual gl::Error setBaseLevel(const gl::Context *context, GLuint baseLevel) = 0;
 
-    virtual void bindTexImage(egl::Surface *surface) = 0;
-    virtual void releaseTexImage() = 0;
+    virtual gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) = 0;
+    virtual gl::Error releaseTexImage(const gl::Context *context) = 0;
 
     virtual void syncState(const gl::Texture::DirtyBits &dirtyBits) = 0;
 
diff --git a/src/libANGLE/renderer/TextureImpl_mock.h b/src/libANGLE/renderer/TextureImpl_mock.h
index 71de0c2..d1245e3 100644
--- a/src/libANGLE/renderer/TextureImpl_mock.h
+++ b/src/libANGLE/renderer/TextureImpl_mock.h
@@ -97,21 +97,27 @@
     MOCK_METHOD2(copyCompressedTexture, gl::Error(const gl::Context *, const gl::Texture *source));
     MOCK_METHOD5(setStorage,
                  gl::Error(const gl::Context *, GLenum, size_t, GLenum, const gl::Extents &));
-    MOCK_METHOD3(setImageExternal,
-                 gl::Error(GLenum, egl::Stream *, const egl::Stream::GLTextureDescription &));
-    MOCK_METHOD2(setEGLImageTarget, gl::Error(GLenum, egl::Image *));
+    MOCK_METHOD4(setImageExternal,
+                 gl::Error(const gl::Context *,
+                           GLenum,
+                           egl::Stream *,
+                           const egl::Stream::GLTextureDescription &));
+    MOCK_METHOD3(setEGLImageTarget, gl::Error(const gl::Context *, GLenum, egl::Image *));
     MOCK_METHOD1(generateMipmap, gl::Error(const gl::Context *));
-    MOCK_METHOD1(bindTexImage, void(egl::Surface *));
-    MOCK_METHOD0(releaseTexImage, void(void));
+    MOCK_METHOD2(bindTexImage, gl::Error(const gl::Context *, egl::Surface *));
+    MOCK_METHOD1(releaseTexImage, gl::Error(const gl::Context *));
 
-    MOCK_METHOD3(getAttachmentRenderTarget,
-                 gl::Error(GLenum, const gl::ImageIndex &, FramebufferAttachmentRenderTarget **));
+    MOCK_METHOD4(getAttachmentRenderTarget,
+                 gl::Error(const gl::Context *,
+                           GLenum,
+                           const gl::ImageIndex &,
+                           FramebufferAttachmentRenderTarget **));
 
     MOCK_METHOD6(
         setStorageMultisample,
         gl::Error(const gl::Context *, GLenum, GLsizei, GLint, const gl::Extents &, GLboolean));
 
-    MOCK_METHOD1(setBaseLevel, void(GLuint));
+    MOCK_METHOD2(setBaseLevel, gl::Error(const gl::Context *, GLuint));
 
     MOCK_METHOD1(syncState, void(const gl::Texture::DirtyBits &));
 
diff --git a/src/libANGLE/renderer/TransformFeedbackImpl.h b/src/libANGLE/renderer/TransformFeedbackImpl.h
index 71e6374..ad371e9 100644
--- a/src/libANGLE/renderer/TransformFeedbackImpl.h
+++ b/src/libANGLE/renderer/TransformFeedbackImpl.h
@@ -26,8 +26,9 @@
     virtual void pause() = 0;
     virtual void resume() = 0;
 
-    virtual void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) = 0;
-    virtual void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) = 0;
+    virtual void bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding) = 0;
+    virtual void bindIndexedBuffer(size_t index,
+                                   const gl::OffsetBindingPointer<gl::Buffer> &binding) = 0;
 
   protected:
     const gl::TransformFeedbackState &mState;
diff --git a/src/libANGLE/renderer/TransformFeedbackImpl_mock.h b/src/libANGLE/renderer/TransformFeedbackImpl_mock.h
index 18832ac..2de3ad7 100644
--- a/src/libANGLE/renderer/TransformFeedbackImpl_mock.h
+++ b/src/libANGLE/renderer/TransformFeedbackImpl_mock.h
@@ -30,8 +30,8 @@
     MOCK_METHOD0(pause, void());
     MOCK_METHOD0(resume, void());
 
-    MOCK_METHOD1(bindGenericBuffer, void(const BindingPointer<gl::Buffer> &));
-    MOCK_METHOD2(bindIndexedBuffer, void(size_t, const OffsetBindingPointer<gl::Buffer> &));
+    MOCK_METHOD1(bindGenericBuffer, void(const gl::BindingPointer<gl::Buffer> &));
+    MOCK_METHOD2(bindIndexedBuffer, void(size_t, const gl::OffsetBindingPointer<gl::Buffer> &));
 
     MOCK_METHOD0(destructor, void());
 };
diff --git a/src/libANGLE/renderer/VertexArrayImpl.h b/src/libANGLE/renderer/VertexArrayImpl.h
index f31cf78..5180aff 100644
--- a/src/libANGLE/renderer/VertexArrayImpl.h
+++ b/src/libANGLE/renderer/VertexArrayImpl.h
@@ -21,11 +21,13 @@
 {
   public:
     VertexArrayImpl(const gl::VertexArrayState &data) : mData(data) {}
-    virtual ~VertexArrayImpl() { }
     virtual void syncState(const gl::Context *context, const gl::VertexArray::DirtyBits &dirtyBits)
     {
     }
 
+    virtual void destroy(const gl::Context *context) {}
+    virtual ~VertexArrayImpl() {}
+
   protected:
     const gl::VertexArrayState &mData;
 };
diff --git a/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/libANGLE/renderer/d3d/DisplayD3D.cpp
index cbc5300..a1e267b 100644
--- a/src/libANGLE/renderer/d3d/DisplayD3D.cpp
+++ b/src/libANGLE/renderer/d3d/DisplayD3D.cpp
@@ -251,7 +251,7 @@
     {
         if (surface->getBoundTexture())
         {
-            surface->releaseTexImage(EGL_BACK_BUFFER);
+            ANGLE_TRY(surface->releaseTexImage(display->getProxyContext(), EGL_BACK_BUFFER));
         }
         SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
         surfaceD3D->releaseSwapChain();
diff --git a/src/libANGLE/renderer/d3d/EGLImageD3D.cpp b/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
index ac9d81c..f78bf2b 100644
--- a/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
+++ b/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
@@ -42,23 +42,24 @@
     return egl::NoError();
 }
 
-gl::Error EGLImageD3D::orphan(egl::ImageSibling *sibling)
+gl::Error EGLImageD3D::orphan(const gl::Context *context, egl::ImageSibling *sibling)
 {
     if (sibling == mState.source.get())
     {
-        ANGLE_TRY(copyToLocalRendertarget());
+        ANGLE_TRY(copyToLocalRendertarget(context));
     }
 
     return gl::NoError();
 }
 
-gl::Error EGLImageD3D::getRenderTarget(RenderTargetD3D **outRT) const
+gl::Error EGLImageD3D::getRenderTarget(const gl::Context *context, RenderTargetD3D **outRT) const
 {
     if (mState.source.get())
     {
         ASSERT(!mRenderTarget);
         FramebufferAttachmentRenderTarget *rt = nullptr;
-        ANGLE_TRY(mState.source->getAttachmentRenderTarget(GL_NONE, mState.imageIndex, &rt));
+        ANGLE_TRY(
+            mState.source->getAttachmentRenderTarget(context, GL_NONE, mState.imageIndex, &rt));
         *outRT = static_cast<RenderTargetD3D *>(rt);
         return gl::NoError();
     }
@@ -70,13 +71,13 @@
     }
 }
 
-gl::Error EGLImageD3D::copyToLocalRendertarget()
+gl::Error EGLImageD3D::copyToLocalRendertarget(const gl::Context *context)
 {
     ASSERT(mState.source.get() != nullptr);
     ASSERT(mRenderTarget == nullptr);
 
     RenderTargetD3D *curRenderTarget = nullptr;
-    ANGLE_TRY(getRenderTarget(&curRenderTarget));
+    ANGLE_TRY(getRenderTarget(context, &curRenderTarget));
 
     // This only currently applies do D3D11, where it invalidates FBOs with this Image attached.
     curRenderTarget->signalDirty();
diff --git a/src/libANGLE/renderer/d3d/EGLImageD3D.h b/src/libANGLE/renderer/d3d/EGLImageD3D.h
index 98e78a3..1ee7984 100644
--- a/src/libANGLE/renderer/d3d/EGLImageD3D.h
+++ b/src/libANGLE/renderer/d3d/EGLImageD3D.h
@@ -11,6 +11,11 @@
 
 #include "libANGLE/renderer/ImageImpl.h"
 
+namespace gl
+{
+class Context;
+}
+
 namespace egl
 {
 class AttributeMap;
@@ -35,12 +40,12 @@
 
     egl::Error initialize() override;
 
-    gl::Error orphan(egl::ImageSibling *sibling) override;
+    gl::Error orphan(const gl::Context *context, egl::ImageSibling *sibling) override;
 
-    gl::Error getRenderTarget(RenderTargetD3D **outRT) const;
+    gl::Error getRenderTarget(const gl::Context *context, RenderTargetD3D **outRT) const;
 
   private:
-    gl::Error copyToLocalRendertarget();
+    gl::Error copyToLocalRendertarget(const gl::Context *context);
 
     RendererD3D *mRenderer;
     RenderTargetD3D *mRenderTarget;
diff --git a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
index 55a49d6..6975b05 100644
--- a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
+++ b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -189,7 +189,7 @@
     return clearImpl(context, clearParams);
 }
 
-GLenum FramebufferD3D::getImplementationColorReadFormat() const
+GLenum FramebufferD3D::getImplementationColorReadFormat(const gl::Context *context) const
 {
     const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
 
@@ -199,7 +199,7 @@
     }
 
     RenderTargetD3D *attachmentRenderTarget = nullptr;
-    gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget);
+    gl::Error error = readAttachment->getRenderTarget(context, &attachmentRenderTarget);
     if (error.isError())
     {
         return GL_NONE;
@@ -212,7 +212,7 @@
     return implementationFormatInfo.getReadPixelsFormat();
 }
 
-GLenum FramebufferD3D::getImplementationColorReadType() const
+GLenum FramebufferD3D::getImplementationColorReadType(const gl::Context *context) const
 {
     const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
 
@@ -222,7 +222,7 @@
     }
 
     RenderTargetD3D *attachmentRenderTarget = nullptr;
-    gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget);
+    gl::Error error = readAttachment->getRenderTarget(context, &attachmentRenderTarget);
     if (error.isError())
     {
         return GL_NONE;
@@ -253,7 +253,7 @@
     ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, packState, false),
                      outputSkipBytes);
 
-    return readPixelsImpl(area, format, type, outputPitch, packState,
+    return readPixelsImpl(context, area, format, type, outputPitch, packState,
                           reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
 }
 
diff --git a/src/libANGLE/renderer/d3d/FramebufferD3D.h b/src/libANGLE/renderer/d3d/FramebufferD3D.h
index eb191e2..b113546 100644
--- a/src/libANGLE/renderer/d3d/FramebufferD3D.h
+++ b/src/libANGLE/renderer/d3d/FramebufferD3D.h
@@ -78,8 +78,8 @@
                             GLfloat depth,
                             GLint stencil) override;
 
-    GLenum getImplementationColorReadFormat() const override;
-    GLenum getImplementationColorReadType() const override;
+    GLenum getImplementationColorReadFormat(const gl::Context *context) const override;
+    GLenum getImplementationColorReadType(const gl::Context *context) const override;
     gl::Error readPixels(const gl::Context *context,
                          const gl::Rectangle &area,
                          GLenum format,
@@ -104,7 +104,8 @@
   private:
     virtual gl::Error clearImpl(const gl::Context *context, const ClearParameters &clearParams) = 0;
 
-    virtual gl::Error readPixelsImpl(const gl::Rectangle &area,
+    virtual gl::Error readPixelsImpl(const gl::Context *context,
+                                     const gl::Rectangle &area,
                                      GLenum format,
                                      GLenum type,
                                      size_t outputPitch,
diff --git a/src/libANGLE/renderer/d3d/ImageD3D.h b/src/libANGLE/renderer/d3d/ImageD3D.h
index ff60362..9d559da 100644
--- a/src/libANGLE/renderer/d3d/ImageD3D.h
+++ b/src/libANGLE/renderer/d3d/ImageD3D.h
@@ -17,6 +17,7 @@
 
 namespace gl
 {
+class Context;
 class Framebuffer;
 struct ImageIndex;
 struct Box;
@@ -51,34 +52,52 @@
 
     virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0;
 
-    virtual gl::Error loadData(const gl::Box &area,
+    virtual gl::Error loadData(const gl::Context *context,
+                               const gl::Box &area,
                                const gl::PixelUnpackState &unpack,
                                GLenum type,
                                const void *input,
                                bool applySkipImages) = 0;
-    virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0;
+    virtual gl::Error loadCompressedData(const gl::Context *context,
+                                         const gl::Box &area,
+                                         const void *input) = 0;
 
-    virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level)
+    virtual gl::Error setManagedSurface2D(const gl::Context *context,
+                                          TextureStorage *storage,
+                                          int level)
     {
         return gl::NoError();
-    };
-    virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level)
+    }
+    virtual gl::Error setManagedSurfaceCube(const gl::Context *context,
+                                            TextureStorage *storage,
+                                            int face,
+                                            int level)
     {
         return gl::NoError();
-    };
-    virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level)
+    }
+    virtual gl::Error setManagedSurface3D(const gl::Context *context,
+                                          TextureStorage *storage,
+                                          int level)
     {
         return gl::NoError();
-    };
-    virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level)
+    }
+    virtual gl::Error setManagedSurface2DArray(const gl::Context *context,
+                                               TextureStorage *storage,
+                                               int layer,
+                                               int level)
     {
         return gl::NoError();
-    };
-    virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
+    }
+    virtual gl::Error copyToStorage(const gl::Context *context,
+                                    TextureStorage *storage,
+                                    const gl::ImageIndex &index,
+                                    const gl::Box &region) = 0;
 
-    virtual gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex,
+    virtual gl::Error copyFromTexStorage(const gl::Context *context,
+                                         const gl::ImageIndex &imageIndex,
                                          TextureStorage *source) = 0;
-    virtual gl::Error copyFromFramebuffer(const gl::Offset &destOffset,
+    virtual gl::Error copyFromFramebuffer(const gl::Context *context,
+                                          const gl::Offset &destOffset,
                                           const gl::Rectangle &sourceArea,
                                           const gl::Framebuffer *source) = 0;
 
diff --git a/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp b/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
index 0791d32..774f3e4 100644
--- a/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
+++ b/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
@@ -75,11 +75,12 @@
     return gl::NoError();
 }
 
-gl::Error RenderbufferD3D::getRenderTarget(RenderTargetD3D **outRenderTarget)
+gl::Error RenderbufferD3D::getRenderTarget(const gl::Context *context,
+                                           RenderTargetD3D **outRenderTarget)
 {
     if (mImage)
     {
-        return mImage->getRenderTarget(outRenderTarget);
+        return mImage->getRenderTarget(context, outRenderTarget);
     }
     else
     {
@@ -88,11 +89,12 @@
     }
 }
 
-gl::Error RenderbufferD3D::getAttachmentRenderTarget(GLenum /*binding*/,
+gl::Error RenderbufferD3D::getAttachmentRenderTarget(const gl::Context *context,
+                                                     GLenum /*binding*/,
                                                      const gl::ImageIndex & /*imageIndex*/,
                                                      FramebufferAttachmentRenderTarget **rtOut)
 {
-    return getRenderTarget(reinterpret_cast<RenderTargetD3D **>(rtOut));
+    return getRenderTarget(context, reinterpret_cast<RenderTargetD3D **>(rtOut));
 }
 
-}
+}  // namespace rx
diff --git a/src/libANGLE/renderer/d3d/RenderbufferD3D.h b/src/libANGLE/renderer/d3d/RenderbufferD3D.h
index 15fd583..c28c37e 100644
--- a/src/libANGLE/renderer/d3d/RenderbufferD3D.h
+++ b/src/libANGLE/renderer/d3d/RenderbufferD3D.h
@@ -34,8 +34,9 @@
                                     size_t height) override;
     gl::Error setStorageEGLImageTarget(egl::Image *image) override;
 
-    gl::Error getRenderTarget(RenderTargetD3D **outRenderTarget);
-    gl::Error getAttachmentRenderTarget(GLenum binding,
+    gl::Error getRenderTarget(const gl::Context *context, RenderTargetD3D **outRenderTarget);
+    gl::Error getAttachmentRenderTarget(const gl::Context *context,
+                                        GLenum binding,
                                         const gl::ImageIndex &imageIndex,
                                         FramebufferAttachmentRenderTarget **rtOut) override;
 
diff --git a/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/libANGLE/renderer/d3d/RendererD3D.cpp
index 28947da..17ec284 100644
--- a/src/libANGLE/renderer/d3d/RendererD3D.cpp
+++ b/src/libANGLE/renderer/d3d/RendererD3D.cpp
@@ -51,7 +51,8 @@
 {
     for (auto &incompleteTexture : mIncompleteTextures)
     {
-        incompleteTexture.second.set(nullptr);
+        incompleteTexture.second->onDestroy(mDisplay->getProxyContext());
+        incompleteTexture.second.set(mDisplay->getProxyContext(), nullptr);
     }
     mIncompleteTextures.clear();
 }
@@ -94,33 +95,33 @@
                 !std::binary_search(framebufferTextures.begin(),
                                     framebufferTextures.begin() + framebufferTextureCount, texture))
             {
-                ANGLE_TRY(setSamplerState(shaderType, samplerIndex, texture, samplerState));
-                ANGLE_TRY(setTexture(shaderType, samplerIndex, texture));
+                ANGLE_TRY(
+                    setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
+                ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture));
             }
             else
             {
                 // Texture is not sampler complete or it is in use by the framebuffer.  Bind the
                 // incomplete texture.
-                gl::Texture *incompleteTexture =
-                    getIncompleteTexture(context->getImplementation(), textureType);
+                gl::Texture *incompleteTexture = getIncompleteTexture(context, textureType);
 
-                ANGLE_TRY(setSamplerState(shaderType, samplerIndex, incompleteTexture,
+                ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
                                           incompleteTexture->getSamplerState()));
-                ANGLE_TRY(setTexture(shaderType, samplerIndex, incompleteTexture));
+                ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture));
             }
         }
         else
         {
             // No texture bound to this slot even though it is used by the shader, bind a NULL
             // texture
-            ANGLE_TRY(setTexture(shaderType, samplerIndex, nullptr));
+            ANGLE_TRY(setTexture(context, shaderType, samplerIndex, nullptr));
         }
     }
 
     // Set all the remaining textures to NULL
     size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? caps.maxTextureImageUnits
                                                             : caps.maxVertexTextureImageUnits;
-    clearTextures(shaderType, samplerRange, samplerCount);
+    clearTextures(context, shaderType, samplerRange, samplerCount);
 
     return gl::NoError();
 }
@@ -173,7 +174,8 @@
     const gl::TransformFeedback *transformFeedback = data.getState().getCurrentTransformFeedback();
     for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
     {
-        const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
+        const gl::OffsetBindingPointer<gl::Buffer> &binding =
+            transformFeedback->getIndexedBuffer(i);
         if (binding.get() != nullptr)
         {
             BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get());
@@ -211,10 +213,11 @@
     return textureCount;
 }
 
-gl::Texture *RendererD3D::getIncompleteTexture(GLImplFactory *implFactory, GLenum type)
+gl::Texture *RendererD3D::getIncompleteTexture(const gl::Context *context, GLenum type)
 {
     if (mIncompleteTextures.find(type) == mIncompleteTextures.end())
     {
+        GLImplFactory *implFactory = context->getImplementation();
         const GLubyte color[] = {0, 0, 0, 255};
         const gl::Extents colorSize(1, 1, 1);
         const gl::PixelUnpackState unpack(1, 0);
@@ -241,7 +244,7 @@
             t->getImplementation()->setSubImage(nullptr, createType, 0, area, GL_RGBA8,
                                                 GL_UNSIGNED_BYTE, unpack, color);
         }
-        mIncompleteTextures[type].set(t);
+        mIncompleteTextures[type].set(context, t);
     }
 
     return mIncompleteTextures[type].get();
diff --git a/src/libANGLE/renderer/d3d/RendererD3D.h b/src/libANGLE/renderer/d3d/RendererD3D.h
index a053a86..d10d2d6 100644
--- a/src/libANGLE/renderer/d3d/RendererD3D.h
+++ b/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -146,8 +146,15 @@
                                            HANDLE shareHandle,
                                            const egl::AttributeMap &attribs) const = 0;
 
-    virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0;
-    virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0;
+    virtual gl::Error setSamplerState(const gl::Context *context,
+                                      gl::SamplerType type,
+                                      int index,
+                                      gl::Texture *texture,
+                                      const gl::SamplerState &sampler) = 0;
+    virtual gl::Error setTexture(const gl::Context *context,
+                                 gl::SamplerType type,
+                                 int index,
+                                 gl::Texture *texture) = 0;
 
     virtual gl::Error setUniformBuffers(const gl::ContextState &data,
                                         const std::vector<GLint> &vertexUniformBuffers,
@@ -207,7 +214,8 @@
                                   bool unpackFlipY,
                                   bool unpackPremultiplyAlpha,
                                   bool unpackUnmultiplyAlpha) = 0;
-    virtual gl::Error copyCompressedTexture(const gl::Texture *source,
+    virtual gl::Error copyCompressedTexture(const gl::Context *context,
+                                            const gl::Texture *source,
                                             GLint sourceLevel,
                                             TextureStorage *storage,
                                             GLint destLevel) = 0;
@@ -236,10 +244,14 @@
 
     // Image operations
     virtual ImageD3D *createImage() = 0;
-    virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0;
-    virtual gl::Error generateMipmapUsingD3D(TextureStorage *storage,
+    virtual gl::Error generateMipmap(const gl::Context *context,
+                                     ImageD3D *dest,
+                                     ImageD3D *source) = 0;
+    virtual gl::Error generateMipmapUsingD3D(const gl::Context *context,
+                                             TextureStorage *storage,
                                              const gl::TextureState &textureState) = 0;
-    virtual gl::Error copyImage(ImageD3D *dest,
+    virtual gl::Error copyImage(const gl::Context *context,
+                                ImageD3D *dest,
                                 ImageD3D *source,
                                 const gl::Rectangle &sourceRect,
                                 const gl::Offset &destOffset,
@@ -283,7 +295,10 @@
     GLint64 getTimestamp();
 
     // In D3D11, faster than calling setTexture a jillion times
-    virtual gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) = 0;
+    virtual gl::Error clearTextures(const gl::Context *context,
+                                    gl::SamplerType samplerType,
+                                    size_t rangeStart,
+                                    size_t rangeEnd) = 0;
 
     virtual egl::Error getEGLDevice(DeviceImpl **device) = 0;
 
@@ -342,7 +357,7 @@
 
     size_t getBoundFramebufferTextures(const gl::ContextState &data,
                                        FramebufferTextureArray *outTextureArray);
-    gl::Texture *getIncompleteTexture(GLImplFactory *implFactory, GLenum type);
+    gl::Texture *getIncompleteTexture(const gl::Context *context, GLenum type);
 
     virtual angle::WorkaroundsD3D generateWorkarounds() const = 0;
 
diff --git a/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
index 86f3adb..4617031 100644
--- a/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+++ b/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
@@ -357,7 +357,8 @@
     return egl::NoError();
 }
 
-gl::Error SurfaceD3D::getAttachmentRenderTarget(GLenum binding,
+gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::Context *context,
+                                                GLenum binding,
                                                 const gl::ImageIndex &imageIndex,
                                                 FramebufferAttachmentRenderTarget **rtOut)
 {
diff --git a/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/libANGLE/renderer/d3d/SurfaceD3D.h
index aa0eab4..9b71599 100644
--- a/src/libANGLE/renderer/d3d/SurfaceD3D.h
+++ b/src/libANGLE/renderer/d3d/SurfaceD3D.h
@@ -57,7 +57,8 @@
     // Returns true if swapchain changed due to resize or interval update
     bool checkForOutOfDateSwapChain(const egl::Display *display);
 
-    gl::Error getAttachmentRenderTarget(GLenum binding,
+    gl::Error getAttachmentRenderTarget(const gl::Context *context,
+                                        GLenum binding,
                                         const gl::ImageIndex &imageIndex,
                                         FramebufferAttachmentRenderTarget **rtOut) override;
 
diff --git a/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/libANGLE/renderer/d3d/TextureD3D.cpp
index a60b2d9..4dede31 100644
--- a/src/libANGLE/renderer/d3d/TextureD3D.cpp
+++ b/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -82,16 +82,17 @@
 
 TextureD3D::~TextureD3D()
 {
+    ASSERT(!mTexStorage);
 }
 
-gl::Error TextureD3D::getNativeTexture(TextureStorage **outStorage)
+gl::Error TextureD3D::getNativeTexture(const gl::Context *context, TextureStorage **outStorage)
 {
     // ensure the underlying texture is created
-    ANGLE_TRY(initializeStorage(false));
+    ANGLE_TRY(initializeStorage(context, false));
 
     if (mTexStorage)
     {
-        ANGLE_TRY(updateStorage());
+        ANGLE_TRY(updateStorage(context));
     }
 
     ASSERT(outStorage);
@@ -100,13 +101,14 @@
     return gl::NoError();
 }
 
-gl::Error TextureD3D::getImageAndSyncFromStorage(const gl::ImageIndex &index,
+gl::Error TextureD3D::getImageAndSyncFromStorage(const gl::Context *context,
+                                                 const gl::ImageIndex &index,
                                                  ImageD3D **outImage) const
 {
     ImageD3D *image = getImage(index);
     if (mTexStorage)
     {
-        ANGLE_TRY(image->copyFromTexStorage(index, mTexStorage));
+        ANGLE_TRY(image->copyFromTexStorage(context, index, mTexStorage));
     }
     *outImage = image;
     return gl::NoError();
@@ -197,7 +199,8 @@
     return (mTexStorage && !internalFormat.compressed);
 }
 
-gl::Error TextureD3D::setImageImpl(const gl::ImageIndex &index,
+gl::Error TextureD3D::setImageImpl(const gl::Context *context,
+                                   const gl::ImageIndex &index,
                                    GLenum type,
                                    const gl::PixelUnpackState &unpack,
                                    const uint8_t *pixels,
@@ -221,12 +224,14 @@
     {
         if (shouldUseSetData(image))
         {
-            ANGLE_TRY(mTexStorage->setData(index, image, nullptr, type, unpack, pixelData));
+            ANGLE_TRY(
+                mTexStorage->setData(context, index, image, nullptr, type, unpack, pixelData));
         }
         else
         {
             gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
-            ANGLE_TRY(image->loadData(fullImageArea, unpack, type, pixelData, index.is3D()));
+            ANGLE_TRY(
+                image->loadData(context, fullImageArea, unpack, type, pixelData, index.is3D()));
         }
 
         mDirtyImages = true;
@@ -235,8 +240,14 @@
     return gl::NoError();
 }
 
-gl::Error TextureD3D::subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type,
-                               const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset)
+gl::Error TextureD3D::subImage(const gl::Context *context,
+                               const gl::ImageIndex &index,
+                               const gl::Box &area,
+                               GLenum format,
+                               GLenum type,
+                               const gl::PixelUnpackState &unpack,
+                               const uint8_t *pixels,
+                               ptrdiff_t layerOffset)
 {
     // CPU readback & copy where direct GPU copy is not supported
     const uint8_t *pixelData = nullptr;
@@ -249,18 +260,19 @@
 
         if (shouldUseSetData(image))
         {
-            return mTexStorage->setData(index, image, &area, type, unpack, pixelData);
+            return mTexStorage->setData(context, index, image, &area, type, unpack, pixelData);
         }
 
-        ANGLE_TRY(image->loadData(area, unpack, type, pixelData, index.is3D()));
-        ANGLE_TRY(commitRegion(index, area));
+        ANGLE_TRY(image->loadData(context, area, unpack, type, pixelData, index.is3D()));
+        ANGLE_TRY(commitRegion(context, index, area));
         mDirtyImages = true;
     }
 
     return gl::NoError();
 }
 
-gl::Error TextureD3D::setCompressedImageImpl(const gl::ImageIndex &index,
+gl::Error TextureD3D::setCompressedImageImpl(const gl::Context *context,
+                                             const gl::ImageIndex &index,
                                              const gl::PixelUnpackState &unpack,
                                              const uint8_t *pixels,
                                              ptrdiff_t layerOffset)
@@ -281,7 +293,7 @@
     if (pixelData != nullptr)
     {
         gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
-        ANGLE_TRY(image->loadCompressedData(fullImageArea, pixelData));
+        ANGLE_TRY(image->loadCompressedData(context, fullImageArea, pixelData));
 
         mDirtyImages = true;
     }
@@ -289,8 +301,12 @@
     return gl::NoError();
 }
 
-gl::Error TextureD3D::subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format,
-                                         const gl::PixelUnpackState &unpack, const uint8_t *pixels,
+gl::Error TextureD3D::subImageCompressed(const gl::Context *context,
+                                         const gl::ImageIndex &index,
+                                         const gl::Box &area,
+                                         GLenum format,
+                                         const gl::PixelUnpackState &unpack,
+                                         const uint8_t *pixels,
                                          ptrdiff_t layerOffset)
 {
     const uint8_t *pixelData = nullptr;
@@ -301,7 +317,7 @@
         ImageD3D *image = getImage(index);
         ASSERT(image);
 
-        ANGLE_TRY(image->loadCompressedData(area, pixelData));
+        ANGLE_TRY(image->loadCompressedData(context, area, pixelData));
 
         mDirtyImages = true;
     }
@@ -379,7 +395,8 @@
     return getImage(getImageIndex(mBaseLevel, 0));
 }
 
-gl::Error TextureD3D::setImageExternal(GLenum target,
+gl::Error TextureD3D::setImageExternal(const gl::Context *context,
+                                       GLenum target,
                                        egl::Stream *stream,
                                        const egl::Stream::GLTextureDescription &desc)
 {
@@ -398,19 +415,19 @@
     {
         // Switch to using the mipmapped texture.
         TextureStorage *textureStorage = nullptr;
-        ANGLE_TRY(getNativeTexture(&textureStorage));
+        ANGLE_TRY(getNativeTexture(context, &textureStorage));
         ANGLE_TRY(textureStorage->useLevelZeroWorkaroundTexture(false));
     }
 
     // Set up proper mipmap chain in our Image array.
-    initMipmapImages();
+    ANGLE_TRY(initMipmapImages(context));
 
     if (mTexStorage && mTexStorage->supportsNativeMipmapFunction())
     {
-        ANGLE_TRY(updateStorage());
+        ANGLE_TRY(updateStorage(context));
 
         // Generate the mipmap chain using the ad-hoc DirectX function.
-        ANGLE_TRY(mRenderer->generateMipmapUsingD3D(mTexStorage, mState));
+        ANGLE_TRY(mRenderer->generateMipmapUsingD3D(context, mTexStorage, mState));
     }
     else
     {
@@ -439,12 +456,12 @@
                 gl::ImageIndex srcIndex = getImageIndex(mBaseLevel, layer);
 
                 ImageD3D *image = getImage(srcIndex);
-                ANGLE_TRY(image->copyFromTexStorage(srcIndex, mTexStorage));
+                ANGLE_TRY(image->copyFromTexStorage(context, srcIndex, mTexStorage));
             }
         }
         else
         {
-            ANGLE_TRY(updateStorage());
+            ANGLE_TRY(updateStorage(context));
         }
     }
 
@@ -472,14 +489,15 @@
             else
             {
                 // CPU-side mipmapping
-                ANGLE_TRY(mRenderer->generateMipmap(getImage(destIndex), getImage(sourceIndex)));
+                ANGLE_TRY(
+                    mRenderer->generateMipmap(context, getImage(destIndex), getImage(sourceIndex)));
             }
         }
     }
 
     if (mTexStorage)
     {
-        updateStorage();
+        updateStorage(context);
     }
 
     return gl::NoError();
@@ -512,9 +530,9 @@
     return false;
 }
 
-gl::Error TextureD3D::ensureRenderTarget()
+gl::Error TextureD3D::ensureRenderTarget(const gl::Context *context)
 {
-    ANGLE_TRY(initializeStorage(true));
+    ANGLE_TRY(initializeStorage(context, true));
 
     // initializeStorage can fail with NoError if the texture is not complete. This is not
     // an error for incomplete sampling, but it is a big problem for rendering.
@@ -529,13 +547,12 @@
         ASSERT(mTexStorage);
         if (!mTexStorage->isRenderTarget())
         {
-            TextureStorage *newRenderTargetStorage = nullptr;
+            TexStoragePointer newRenderTargetStorage(context);
             ANGLE_TRY(createCompleteStorage(true, &newRenderTargetStorage));
 
-            std::unique_ptr<TextureStorage> newStorageRef(newRenderTargetStorage);
-            ANGLE_TRY(mTexStorage->copyToStorage(newRenderTargetStorage));
-            ANGLE_TRY(setCompleteTexStorage(newRenderTargetStorage));
-            newStorageRef.release();
+            ANGLE_TRY(mTexStorage->copyToStorage(context, newRenderTargetStorage.get()));
+            ANGLE_TRY(setCompleteTexStorage(context, newRenderTargetStorage.get()));
+            newRenderTargetStorage.release();
         }
     }
 
@@ -549,30 +566,33 @@
     return (image->isRenderableFormat() && levelsComplete);
 }
 
-gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box &region)
+gl::Error TextureD3D::commitRegion(const gl::Context *context,
+                                   const gl::ImageIndex &index,
+                                   const gl::Box &region)
 {
     if (mTexStorage)
     {
         ASSERT(isValidIndex(index));
         ImageD3D *image = getImage(index);
-        ANGLE_TRY(image->copyToStorage(mTexStorage, index, region));
+        ANGLE_TRY(image->copyToStorage(context, mTexStorage, index, region));
         image->markClean();
     }
 
     return gl::NoError();
 }
 
-gl::Error TextureD3D::getAttachmentRenderTarget(GLenum /*binding*/,
+gl::Error TextureD3D::getAttachmentRenderTarget(const gl::Context *context,
+                                                GLenum /*binding*/,
                                                 const gl::ImageIndex &imageIndex,
                                                 FramebufferAttachmentRenderTarget **rtOut)
 {
     RenderTargetD3D *rtD3D = nullptr;
-    gl::Error error        = getRenderTarget(imageIndex, &rtD3D);
+    gl::Error error        = getRenderTarget(context, imageIndex, &rtD3D);
     *rtOut = static_cast<FramebufferAttachmentRenderTarget *>(rtD3D);
     return error;
 }
 
-void TextureD3D::setBaseLevel(GLuint baseLevel)
+gl::Error TextureD3D::setBaseLevel(const gl::Context *context, GLuint baseLevel)
 {
     const int oldStorageWidth  = std::max(1, getLevelZeroWidth());
     const int oldStorageHeight = std::max(1, getLevelZeroHeight());
@@ -591,8 +611,10 @@
          newStorageDepth != oldStorageDepth || newStorageFormat != oldStorageFormat))
     {
         markAllImagesDirty();
-        SafeDelete(mTexStorage);
+        ANGLE_TRY(releaseTexStorage(context));
     }
+
+    return gl::NoError();
 }
 
 void TextureD3D::syncState(const gl::Texture::DirtyBits &dirtyBits)
@@ -600,6 +622,22 @@
     // TODO(geofflang): Use dirty bits
 }
 
+gl::Error TextureD3D::releaseTexStorage(const gl::Context *context)
+{
+    if (!mTexStorage)
+    {
+        return gl::NoError();
+    }
+    ANGLE_TRY(mTexStorage->onDestroy(context));
+    mTexStorage = nullptr;
+    return gl::NoError();
+}
+
+gl::Error TextureD3D::onDestroy(const gl::Context *context)
+{
+    return releaseTexStorage(context);
+}
+
 TextureD3D_2D::TextureD3D_2D(const gl::TextureState &state, RendererD3D *renderer)
     : TextureD3D(state, renderer)
 {
@@ -711,7 +749,8 @@
     return gl::InternalError();
 }
 
-gl::Error TextureD3D_2DMultisample::setImageExternal(GLenum target,
+gl::Error TextureD3D_2DMultisample::setImageExternal(const gl::Context *context,
+                                                     GLenum target,
                                                      egl::Stream *stream,
                                                      const egl::Stream::GLTextureDescription &desc)
 {
@@ -719,23 +758,28 @@
     return gl::InternalError();
 }
 
-void TextureD3D_2DMultisample::bindTexImage(egl::Surface *surface)
-{
-    UNIMPLEMENTED();
-}
-
-void TextureD3D_2DMultisample::releaseTexImage()
-{
-    UNIMPLEMENTED();
-}
-
-gl::Error TextureD3D_2DMultisample::setEGLImageTarget(GLenum target, egl::Image *image)
+gl::Error TextureD3D_2DMultisample::bindTexImage(const gl::Context *context, egl::Surface *surface)
 {
     UNIMPLEMENTED();
     return gl::InternalError();
 }
 
-gl::Error TextureD3D_2DMultisample::getRenderTarget(const gl::ImageIndex &index,
+gl::Error TextureD3D_2DMultisample::releaseTexImage(const gl::Context *context)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::setEGLImageTarget(const gl::Context *context,
+                                                      GLenum target,
+                                                      egl::Image *image)
+{
+    UNIMPLEMENTED();
+    return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::getRenderTarget(const gl::Context *context,
+                                                    const gl::ImageIndex &index,
                                                     RenderTargetD3D **outRT)
 {
     UNIMPLEMENTED();
@@ -771,34 +815,36 @@
     UNIMPLEMENTED();
 }
 
-gl::Error TextureD3D_2DMultisample::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_2DMultisample::initializeStorage(const gl::Context *context, bool renderTarget)
 {
     UNIMPLEMENTED();
     return gl::InternalError();
 }
 
 gl::Error TextureD3D_2DMultisample::createCompleteStorage(bool renderTarget,
-                                                          TextureStorage **outTexStorage) const
+                                                          TexStoragePointer *outStorage) const
 {
     UNIMPLEMENTED();
     return gl::InternalError();
 }
 
-gl::Error TextureD3D_2DMultisample::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_2DMultisample::setCompleteTexStorage(const gl::Context *context,
+                                                          TextureStorage *newCompleteTexStorage)
 {
     UNIMPLEMENTED();
     return gl::InternalError();
 }
 
-gl::Error TextureD3D_2DMultisample::updateStorage()
+gl::Error TextureD3D_2DMultisample::updateStorage(const gl::Context *context)
 {
     UNIMPLEMENTED();
     return gl::InternalError();
 }
 
-void TextureD3D_2DMultisample::initMipmapImages()
+gl::Error TextureD3D_2DMultisample::initMipmapImages(const gl::Context *context)
 {
     UNIMPLEMENTED();
+    return gl::InternalError();
 }
 
 bool TextureD3D_2DMultisample::isImageComplete(const gl::ImageIndex &index) const
@@ -816,8 +862,6 @@
     {
         SafeDelete(mImageArray[i]);
     }
-
-    SafeDelete(mTexStorage);
 }
 
 ImageD3D *TextureD3D_2D::getImage(int level, int layer) const
@@ -887,8 +931,8 @@
     bool fastUnpacked = false;
     GLint level       = static_cast<GLint>(imageLevel);
 
-    redefineImage(level, internalFormatInfo.sizedInternalFormat, size,
-                  shouldForceReleaseImagesOnSetImage(pixels));
+    ANGLE_TRY(redefineImage(context, level, internalFormatInfo.sizedInternalFormat, size,
+                            shouldForceReleaseImagesOnSetImage(pixels)));
 
     gl::ImageIndex index = gl::ImageIndex::Make2D(level);
 
@@ -897,7 +941,7 @@
     {
         // Will try to create RT storage if it does not exist
         RenderTargetD3D *destRenderTarget = nullptr;
-        ANGLE_TRY(getRenderTarget(index, &destRenderTarget));
+        ANGLE_TRY(getRenderTarget(context, index, &destRenderTarget));
 
         gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
 
@@ -912,7 +956,7 @@
 
     if (!fastUnpacked)
     {
-        ANGLE_TRY(setImageImpl(index, type, unpack, pixels, 0));
+        ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, 0));
     }
 
     return gl::NoError();
@@ -934,7 +978,7 @@
     if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
     {
         RenderTargetD3D *renderTarget = nullptr;
-        ANGLE_TRY(getRenderTarget(index, &renderTarget));
+        ANGLE_TRY(getRenderTarget(context, index, &renderTarget));
         ASSERT(!mImageArray[level]->isDirty());
 
         return fastUnpackPixels(context, unpack, pixels, area, getInternalFormat(level), type,
@@ -942,7 +986,7 @@
     }
     else
     {
-        return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
+        return TextureD3D::subImage(context, index, area, format, type, unpack, pixels, 0);
     }
 }
 
@@ -959,9 +1003,10 @@
     GLint level = static_cast<GLint>(imageLevel);
 
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
-    redefineImage(level, internalFormat, size, shouldForceReleaseImagesOnSetImage(pixels));
+    ANGLE_TRY(redefineImage(context, level, internalFormat, size,
+                            shouldForceReleaseImagesOnSetImage(pixels)));
 
-    return setCompressedImageImpl(gl::ImageIndex::Make2D(level), unpack, pixels, 0);
+    return setCompressedImageImpl(context, gl::ImageIndex::Make2D(level), unpack, pixels, 0);
 }
 
 gl::Error TextureD3D_2D::setCompressedSubImage(const gl::Context *context,
@@ -976,9 +1021,9 @@
     ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);
 
     gl::ImageIndex index = gl::ImageIndex::Make2D(static_cast<GLint>(level));
-    ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0));
+    ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
 
-    return commitRegion(index, area);
+    return commitRegion(context, index, area);
 }
 
 gl::Error TextureD3D_2D::copyImage(const gl::Context *context,
@@ -993,9 +1038,9 @@
     GLint level                = static_cast<GLint>(imageLevel);
     const gl::InternalFormat &internalFormatInfo =
         gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
-    redefineImage(level, internalFormatInfo.sizedInternalFormat,
-                  gl::Extents(sourceArea.width, sourceArea.height, 1),
-                  mRenderer->isRobustResourceInitEnabled());
+    ANGLE_TRY(redefineImage(context, level, internalFormatInfo.sizedInternalFormat,
+                            gl::Extents(sourceArea.width, sourceArea.height, 1),
+                            mRenderer->isRobustResourceInitEnabled()));
 
     gl::ImageIndex index = gl::ImageIndex::Make2D(level);
     gl::Offset destOffset(0, 0, 0);
@@ -1004,12 +1049,12 @@
     // so we should use the non-rendering copy path.
     if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
     {
-        ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source));
+        ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(context, destOffset, sourceArea, source));
         mDirtyImages = true;
     }
     else
     {
-        ANGLE_TRY(ensureRenderTarget());
+        ANGLE_TRY(ensureRenderTarget(context));
         mImageArray[level]->markClean();
 
         if (sourceArea.width != 0 && sourceArea.height != 0 && isValidLevel(level))
@@ -1041,16 +1086,16 @@
     // so we should use the non-rendering copy path.
     if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
     {
-        ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source));
+        ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(context, destOffset, sourceArea, source));
         mDirtyImages = true;
     }
     else
     {
-        ANGLE_TRY(ensureRenderTarget());
+        ANGLE_TRY(ensureRenderTarget(context));
 
         if (isValidLevel(level))
         {
-            ANGLE_TRY(updateStorageLevel(level));
+            ANGLE_TRY(updateStorageLevel(context, level));
             ANGLE_TRY(mRenderer->copyImage2D(context, source, sourceArea,
                                              gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
                                              destOffset, mTexStorage, level));
@@ -1080,16 +1125,17 @@
     const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
     gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
                      static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
-    redefineImage(destLevel, internalFormatInfo.sizedInternalFormat, size, false);
+    ANGLE_TRY(
+        redefineImage(context, destLevel, internalFormatInfo.sizedInternalFormat, size, false));
 
     gl::Rectangle sourceRect(0, 0, size.width, size.height);
     gl::Offset destOffset(0, 0, 0);
 
     if (canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel)))
     {
-        ANGLE_TRY(ensureRenderTarget());
+        ANGLE_TRY(ensureRenderTarget(context));
         ASSERT(isValidLevel(destLevel));
-        ANGLE_TRY(updateStorageLevel(destLevel));
+        ANGLE_TRY(updateStorageLevel(context, destLevel));
 
         ANGLE_TRY(mRenderer->copyTexture(context, source, static_cast<GLint>(sourceLevel),
                                          sourceRect, internalFormatInfo.format, destOffset,
@@ -1101,14 +1147,14 @@
         gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel));
         TextureD3D *sourceD3D           = GetImplAs<TextureD3D>(source);
         ImageD3D *sourceImage           = nullptr;
-        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(sourceImageIndex, &sourceImage));
+        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
 
         gl::ImageIndex destImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(destLevel));
         ImageD3D *destImage           = nullptr;
-        ANGLE_TRY(getImageAndSyncFromStorage(destImageIndex, &destImage));
+        ANGLE_TRY(getImageAndSyncFromStorage(context, destImageIndex, &destImage));
 
-        ANGLE_TRY(mRenderer->copyImage(destImage, sourceImage, sourceRect, destOffset, unpackFlipY,
-                                       unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+        ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceRect, destOffset,
+                                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
     }
 
     return gl::NoError();
@@ -1131,9 +1177,9 @@
 
     if (canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel)))
     {
-        ANGLE_TRY(ensureRenderTarget());
+        ANGLE_TRY(ensureRenderTarget(context));
         ASSERT(isValidLevel(destLevel));
-        ANGLE_TRY(updateStorageLevel(destLevel));
+        ANGLE_TRY(updateStorageLevel(context, destLevel));
 
         ANGLE_TRY(mRenderer->copyTexture(
             context, source, static_cast<GLint>(sourceLevel), sourceArea,
@@ -1145,14 +1191,14 @@
         gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel));
         TextureD3D *sourceD3D           = GetImplAs<TextureD3D>(source);
         ImageD3D *sourceImage           = nullptr;
-        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(sourceImageIndex, &sourceImage));
+        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
 
         gl::ImageIndex destImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(destLevel));
         ImageD3D *destImage           = nullptr;
-        ANGLE_TRY(getImageAndSyncFromStorage(destImageIndex, &destImage));
+        ANGLE_TRY(getImageAndSyncFromStorage(context, destImageIndex, &destImage));
 
-        ANGLE_TRY(mRenderer->copyImage(destImage, sourceImage, sourceArea, destOffset, unpackFlipY,
-                                       unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+        ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceArea, destOffset,
+                                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
     }
 
     return gl::NoError();
@@ -1170,12 +1216,13 @@
         source->getFormat(sourceTarget, sourceLevel).info->sizedInternalFormat;
     gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
                      static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
-    redefineImage(destLevel, sizedInternalFormat, size, false);
+    ANGLE_TRY(redefineImage(context, destLevel, sizedInternalFormat, size, false));
 
-    ANGLE_TRY(initializeStorage(false));
+    ANGLE_TRY(initializeStorage(context, false));
     ASSERT(mTexStorage);
 
-    ANGLE_TRY(mRenderer->copyCompressedTexture(source, sourceLevel, mTexStorage, destLevel));
+    ANGLE_TRY(
+        mRenderer->copyCompressedTexture(context, source, sourceLevel, mTexStorage, destLevel));
 
     return gl::NoError();
 }
@@ -1193,44 +1240,38 @@
         gl::Extents levelSize(std::max(1, size.width >> level),
                               std::max(1, size.height >> level),
                               1);
-        redefineImage(level, internalFormat, levelSize, true);
+        ANGLE_TRY(redefineImage(context, level, internalFormat, levelSize, true));
     }
 
     for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
     {
-        redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true);
+        ANGLE_TRY(redefineImage(context, level, GL_NONE, gl::Extents(0, 0, 1), true));
     }
 
     // TODO(geofflang): Verify storage creation had no errors
-    bool renderTarget       = IsRenderTargetUsage(mState.getUsage());
-    TextureStorage *storage = mRenderer->createTextureStorage2D(
-        internalFormat, renderTarget, size.width, size.height, static_cast<int>(levels), false);
+    bool renderTarget = IsRenderTargetUsage(mState.getUsage());
+    TexStoragePointer storage(context);
+    storage.reset(mRenderer->createTextureStorage2D(internalFormat, renderTarget, size.width,
+                                                    size.height, static_cast<int>(levels), false));
 
-    gl::Error error = setCompleteTexStorage(storage);
-    if (error.isError())
-    {
-        SafeDelete(storage);
-        return error;
-    }
+    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+    storage.release();
 
-    ANGLE_TRY(updateStorage());
+    ANGLE_TRY(updateStorage(context));
 
     mImmutable = true;
 
     return gl::NoError();
 }
 
-void TextureD3D_2D::bindTexImage(egl::Surface *surface)
+gl::Error TextureD3D_2D::bindTexImage(const gl::Context *context, egl::Surface *surface)
 {
     GLenum internalformat = surface->getConfig()->renderTargetFormat;
 
     gl::Extents size(surface->getWidth(), surface->getHeight(), 1);
-    redefineImage(0, internalformat, size, true);
+    ANGLE_TRY(redefineImage(context, 0, internalformat, size, true));
 
-    if (mTexStorage)
-    {
-        SafeDelete(mTexStorage);
-    }
+    ANGLE_TRY(releaseTexStorage(context));
 
     SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
     ASSERT(surfaceD3D);
@@ -1239,42 +1280,47 @@
     mEGLImageTarget = false;
 
     mDirtyImages = true;
+    return gl::NoError();
 }
 
-void TextureD3D_2D::releaseTexImage()
+gl::Error TextureD3D_2D::releaseTexImage(const gl::Context *context)
 {
     if (mTexStorage)
     {
-        SafeDelete(mTexStorage);
+        ANGLE_TRY(releaseTexStorage(context));
     }
 
     for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
     {
-        redefineImage(i, GL_NONE, gl::Extents(0, 0, 1), true);
+        ANGLE_TRY(redefineImage(context, i, GL_NONE, gl::Extents(0, 0, 1), true));
     }
+
+    return gl::NoError();
 }
 
-gl::Error TextureD3D_2D::setEGLImageTarget(GLenum target, egl::Image *image)
+gl::Error TextureD3D_2D::setEGLImageTarget(const gl::Context *context,
+                                           GLenum target,
+                                           egl::Image *image)
 {
     EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image);
 
     // Set the properties of the base mip level from the EGL image
     const auto &format = image->getFormat();
     gl::Extents size(static_cast<int>(image->getWidth()), static_cast<int>(image->getHeight()), 1);
-    redefineImage(0, format.info->sizedInternalFormat, size, true);
+    ANGLE_TRY(redefineImage(context, 0, format.info->sizedInternalFormat, size, true));
 
     // Clear all other images.
     for (size_t level = 1; level < ArraySize(mImageArray); level++)
     {
-        redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true);
+        ANGLE_TRY(redefineImage(context, level, GL_NONE, gl::Extents(0, 0, 1), true));
     }
 
-    SafeDelete(mTexStorage);
+    ANGLE_TRY(releaseTexStorage(context));
     mImageArray[0]->markClean();
 
     // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error.
     RenderTargetD3D *renderTargetD3D = nullptr;
-    ANGLE_TRY(eglImaged3d->getRenderTarget(&renderTargetD3D));
+    ANGLE_TRY(eglImaged3d->getRenderTarget(context, &renderTargetD3D));
 
     mTexStorage     = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D);
     mEGLImageTarget = true;
@@ -1282,7 +1328,7 @@
     return gl::NoError();
 }
 
-void TextureD3D_2D::initMipmapImages()
+gl::Error TextureD3D_2D::initMipmapImages(const gl::Context *context)
 {
     const GLuint baseLevel = mState.getEffectiveBaseLevel();
     const GLuint maxLevel  = mState.getMipmapMaxLevel();
@@ -1293,19 +1339,22 @@
         gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1),
                               std::max(getLevelZeroHeight() >> level, 1), 1);
 
-        redefineImage(level, getBaseLevelInternalFormat(), levelSize, false);
+        ANGLE_TRY(redefineImage(context, level, getBaseLevelInternalFormat(), levelSize, false));
     }
+    return gl::NoError();
 }
 
-gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureD3D_2D::getRenderTarget(const gl::Context *context,
+                                         const gl::ImageIndex &index,
+                                         RenderTargetD3D **outRT)
 {
     ASSERT(!index.hasLayer());
 
     // ensure the underlying texture is created
-    ANGLE_TRY(ensureRenderTarget());
-    ANGLE_TRY(updateStorageLevel(index.mipIndex));
+    ANGLE_TRY(ensureRenderTarget(context));
+    ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
 
-    return mTexStorage->getRenderTarget(index, outRT);
+    return mTexStorage->getRenderTarget(context, index, outRT);
 }
 
 bool TextureD3D_2D::isValidLevel(int level) const
@@ -1361,7 +1410,7 @@
 }
 
 // Constructs a native texture resource from the texture images
-gl::Error TextureD3D_2D::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_2D::initializeStorage(const gl::Context *context, bool renderTarget)
 {
     // Only initialize the first time this texture is used as a render target or shader resource
     if (mTexStorage)
@@ -1377,25 +1426,22 @@
 
     bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
 
-    TextureStorage *storage = nullptr;
+    TexStoragePointer storage(context);
     ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
 
-    gl::Error error = setCompleteTexStorage(storage);
-    if (error.isError())
-    {
-        SafeDelete(storage);
-        return error;
-    }
+    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+    storage.release();
 
     ASSERT(mTexStorage);
 
     // flush image data to the storage
-    ANGLE_TRY(updateStorage());
+    ANGLE_TRY(updateStorage(context));
 
     return gl::NoError();
 }
 
-gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const
+gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget,
+                                               TexStoragePointer *outStorage) const
 {
     GLsizei width         = getLevelZeroWidth();
     GLsizei height        = getLevelZeroHeight();
@@ -1419,22 +1465,25 @@
     }
 
     // TODO(geofflang): Determine if the texture creation succeeded
-    *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels, hintLevelZeroOnly);
+    outStorage->reset(mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height,
+                                                        levels, hintLevelZeroOnly));
 
     return gl::NoError();
 }
 
-gl::Error TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_2D::setCompleteTexStorage(const gl::Context *context,
+                                               TextureStorage *newCompleteTexStorage)
 {
     if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
     {
         for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
         {
-            ANGLE_TRY(mImageArray[level]->setManagedSurface2D(newCompleteTexStorage, level));
+            ANGLE_TRY(
+                mImageArray[level]->setManagedSurface2D(context, newCompleteTexStorage, level));
         }
     }
 
-    SafeDelete(mTexStorage);
+    ANGLE_TRY(releaseTexStorage(context));
     mTexStorage = newCompleteTexStorage;
 
     mDirtyImages = true;
@@ -1442,7 +1491,7 @@
     return gl::NoError();
 }
 
-gl::Error TextureD3D_2D::updateStorage()
+gl::Error TextureD3D_2D::updateStorage(const gl::Context *context)
 {
     ASSERT(mTexStorage != nullptr);
     GLint storageLevels = mTexStorage->getLevelCount();
@@ -1450,14 +1499,14 @@
     {
         if (mImageArray[level]->isDirty() && isLevelComplete(level))
         {
-            ANGLE_TRY(updateStorageLevel(level));
+            ANGLE_TRY(updateStorageLevel(context, level));
         }
     }
 
     return gl::NoError();
 }
 
-gl::Error TextureD3D_2D::updateStorageLevel(int level)
+gl::Error TextureD3D_2D::updateStorageLevel(const gl::Context *context, int level)
 {
     ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != nullptr);
     ASSERT(isLevelComplete(level));
@@ -1466,16 +1515,17 @@
     {
         gl::ImageIndex index = gl::ImageIndex::Make2D(level);
         gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
-        ANGLE_TRY(commitRegion(index, region));
+        ANGLE_TRY(commitRegion(context, index, region));
     }
 
     return gl::NoError();
 }
 
-void TextureD3D_2D::redefineImage(size_t level,
-                                  GLenum internalformat,
-                                  const gl::Extents &size,
-                                  bool forceRelease)
+gl::Error TextureD3D_2D::redefineImage(const gl::Context *context,
+                                       size_t level,
+                                       GLenum internalformat,
+                                       const gl::Extents &size,
+                                       bool forceRelease)
 {
     ASSERT(size.depth == 1);
 
@@ -1495,21 +1545,23 @@
         // while orphaning
         if (level != 0 && mEGLImageTarget)
         {
-            // TODO(jmadill): Don't discard error.
-            mImageArray[0]->copyFromTexStorage(gl::ImageIndex::Make2D(0), mTexStorage);
+            ANGLE_TRY(mImageArray[0]->copyFromTexStorage(context, gl::ImageIndex::Make2D(0),
+                                                         mTexStorage));
         }
 
         if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
             size.height != storageHeight ||
             internalformat != storageFormat)  // Discard mismatched storage
         {
-            SafeDelete(mTexStorage);
+            ANGLE_TRY(releaseTexStorage(context));
             markAllImagesDirty();
         }
     }
 
     // Can't be an EGL image target after being redefined
     mEGLImageTarget = false;
+
+    return gl::NoError();
 }
 
 gl::ImageIndexIterator TextureD3D_2D::imageIterator() const
@@ -1573,8 +1625,6 @@
             SafeDelete(mImageArray[i][j]);
         }
     }
-
-    SafeDelete(mTexStorage);
 }
 
 ImageD3D *TextureD3D_Cube::getImage(int level, int layer) const
@@ -1610,7 +1660,9 @@
     return gl::GetSizedInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0;
 }
 
-gl::Error TextureD3D_Cube::setEGLImageTarget(GLenum target, egl::Image *image)
+gl::Error TextureD3D_Cube::setEGLImageTarget(const gl::Context *context,
+                                             GLenum target,
+                                             egl::Image *image)
 {
     UNREACHABLE();
     return gl::InternalError();
@@ -1631,11 +1683,11 @@
     const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
     gl::ImageIndex index       = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
 
-    redefineImage(index.layerIndex, static_cast<GLint>(level),
-                  internalFormatInfo.sizedInternalFormat, size,
-                  shouldForceReleaseImagesOnSetImage(pixels));
+    ANGLE_TRY(redefineImage(context, index.layerIndex, static_cast<GLint>(level),
+                            internalFormatInfo.sizedInternalFormat, size,
+                            shouldForceReleaseImagesOnSetImage(pixels)));
 
-    return setImageImpl(index, type, unpack, pixels, 0);
+    return setImageImpl(context, index, type, unpack, pixels, 0);
 }
 
 gl::Error TextureD3D_Cube::setSubImage(const gl::Context *context,
@@ -1650,7 +1702,7 @@
     ASSERT(area.depth == 1 && area.z == 0);
 
     gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
-    return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
+    return TextureD3D::subImage(context, index, area, format, type, unpack, pixels, 0);
 }
 
 gl::Error TextureD3D_Cube::setCompressedImage(const gl::Context *context,
@@ -1667,11 +1719,11 @@
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
     size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target);
 
-    redefineImage(static_cast<int>(faceIndex), static_cast<GLint>(level), internalFormat, size,
-                  shouldForceReleaseImagesOnSetImage(pixels));
+    ANGLE_TRY(redefineImage(context, static_cast<int>(faceIndex), static_cast<GLint>(level),
+                            internalFormat, size, shouldForceReleaseImagesOnSetImage(pixels)));
 
     gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
-    return setCompressedImageImpl(index, unpack, pixels, 0);
+    return setCompressedImageImpl(context, index, unpack, pixels, 0);
 }
 
 gl::Error TextureD3D_Cube::setCompressedSubImage(const gl::Context *context,
@@ -1687,8 +1739,8 @@
 
     gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
 
-    ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0));
-    return commitRegion(index, area);
+    ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
+    return commitRegion(context, index, area);
 }
 
 gl::Error TextureD3D_Cube::copyImage(const gl::Context *context,
@@ -1705,8 +1757,9 @@
     GLint level = static_cast<GLint>(imageLevel);
 
     gl::Extents size(sourceArea.width, sourceArea.height, 1);
-    redefineImage(static_cast<int>(faceIndex), level, internalFormatInfo.sizedInternalFormat, size,
-                  mRenderer->isRobustResourceInitEnabled());
+    ANGLE_TRY(redefineImage(context, static_cast<int>(faceIndex), level,
+                            internalFormatInfo.sizedInternalFormat, size,
+                            mRenderer->isRobustResourceInitEnabled()));
 
     gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
     gl::Offset destOffset(0, 0, 0);
@@ -1715,13 +1768,13 @@
     // so we should use the non-rendering copy path.
     if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
     {
-        ANGLE_TRY(
-            mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source));
+        ANGLE_TRY(mImageArray[faceIndex][level]->copyFromFramebuffer(context, destOffset,
+                                                                     sourceArea, source));
         mDirtyImages = true;
     }
     else
     {
-        ANGLE_TRY(ensureRenderTarget());
+        ANGLE_TRY(ensureRenderTarget(context));
         mImageArray[faceIndex][level]->markClean();
 
         ASSERT(size.width == size.height);
@@ -1752,8 +1805,8 @@
     // so we should use the non-rendering copy path.
     if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
     {
-        gl::Error error =
-            mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source);
+        gl::Error error = mImageArray[faceIndex][level]->copyFromFramebuffer(context, destOffset,
+                                                                             sourceArea, source);
         if (error.isError())
         {
             return error;
@@ -1763,10 +1816,10 @@
     }
     else
     {
-        ANGLE_TRY(ensureRenderTarget());
+        ANGLE_TRY(ensureRenderTarget(context));
         if (isValidFaceLevel(faceIndex, level))
         {
-            ANGLE_TRY(updateStorageFaceLevel(faceIndex, level));
+            ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, level));
             ANGLE_TRY(mRenderer->copyImageCube(context, source, sourceArea,
                                                gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
                                                destOffset, mTexStorage, target, level));
@@ -1797,16 +1850,17 @@
     const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
     gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
                      static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
-    redefineImage(faceIndex, destLevel, internalFormatInfo.sizedInternalFormat, size, false);
+    ANGLE_TRY(redefineImage(context, faceIndex, destLevel, internalFormatInfo.sizedInternalFormat,
+                            size, false));
 
     gl::Rectangle sourceRect(0, 0, size.width, size.height);
     gl::Offset destOffset(0, 0, 0);
 
     if (canCreateRenderTargetForImage(gl::ImageIndex::MakeCube(target, destLevel)))
     {
-        ANGLE_TRY(ensureRenderTarget());
+        ANGLE_TRY(ensureRenderTarget(context));
         ASSERT(isValidFaceLevel(faceIndex, destLevel));
-        ANGLE_TRY(updateStorageFaceLevel(faceIndex, destLevel));
+        ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, destLevel));
 
         ANGLE_TRY(mRenderer->copyTexture(context, source, static_cast<GLint>(sourceLevel),
                                          sourceRect, internalFormatInfo.format, destOffset,
@@ -1818,15 +1872,15 @@
         gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel));
         TextureD3D *sourceD3D           = GetImplAs<TextureD3D>(source);
         ImageD3D *sourceImage           = nullptr;
-        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(sourceImageIndex, &sourceImage));
+        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
 
         gl::ImageIndex destImageIndex =
             gl::ImageIndex::MakeCube(target, static_cast<GLint>(destLevel));
         ImageD3D *destImage = nullptr;
-        ANGLE_TRY(getImageAndSyncFromStorage(destImageIndex, &destImage));
+        ANGLE_TRY(getImageAndSyncFromStorage(context, destImageIndex, &destImage));
 
-        ANGLE_TRY(mRenderer->copyImage(destImage, sourceImage, sourceRect, destOffset, unpackFlipY,
-                                       unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+        ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceRect, destOffset,
+                                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
     }
 
     return gl::NoError();
@@ -1850,9 +1904,9 @@
 
     if (canCreateRenderTargetForImage(gl::ImageIndex::MakeCube(target, destLevel)))
     {
-        ANGLE_TRY(ensureRenderTarget());
+        ANGLE_TRY(ensureRenderTarget(context));
         ASSERT(isValidFaceLevel(faceIndex, destLevel));
-        ANGLE_TRY(updateStorageFaceLevel(faceIndex, destLevel));
+        ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, destLevel));
 
         ANGLE_TRY(mRenderer->copyTexture(
             context, source, static_cast<GLint>(sourceLevel), sourceArea,
@@ -1864,15 +1918,15 @@
         gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel));
         TextureD3D *sourceD3D           = GetImplAs<TextureD3D>(source);
         ImageD3D *sourceImage           = nullptr;
-        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(sourceImageIndex, &sourceImage));
+        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
 
         gl::ImageIndex destImageIndex =
             gl::ImageIndex::MakeCube(target, static_cast<GLint>(destLevel));
         ImageD3D *destImage = nullptr;
-        ANGLE_TRY(getImageAndSyncFromStorage(destImageIndex, &destImage));
+        ANGLE_TRY(getImageAndSyncFromStorage(context, destImageIndex, &destImage));
 
-        ANGLE_TRY(mRenderer->copyImage(destImage, sourceImage, sourceArea, destOffset, unpackFlipY,
-                                       unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+        ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceArea, destOffset,
+                                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
     }
 
     return gl::NoError();
@@ -1907,17 +1961,14 @@
     // TODO(geofflang): Verify storage creation had no errors
     bool renderTarget = IsRenderTargetUsage(mState.getUsage());
 
-    TextureStorage *storage = mRenderer->createTextureStorageCube(
-        internalFormat, renderTarget, size.width, static_cast<int>(levels), false);
+    TexStoragePointer storage(context);
+    storage.reset(mRenderer->createTextureStorageCube(internalFormat, renderTarget, size.width,
+                                                      static_cast<int>(levels), false));
 
-    gl::Error error = setCompleteTexStorage(storage);
-    if (error.isError())
-    {
-        SafeDelete(storage);
-        return error;
-    }
+    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+    storage.release();
 
-    ANGLE_TRY(updateStorage());
+    ANGLE_TRY(updateStorage(context));
 
     mImmutable = true;
 
@@ -1951,17 +2002,19 @@
     return true;
 }
 
-void TextureD3D_Cube::bindTexImage(egl::Surface *surface)
+gl::Error TextureD3D_Cube::bindTexImage(const gl::Context *context, egl::Surface *surface)
 {
     UNREACHABLE();
+    return gl::InternalError();
 }
 
-void TextureD3D_Cube::releaseTexImage()
+gl::Error TextureD3D_Cube::releaseTexImage(const gl::Context *context)
 {
     UNREACHABLE();
+    return gl::InternalError();
 }
 
-void TextureD3D_Cube::initMipmapImages()
+gl::Error TextureD3D_Cube::initMipmapImages(const gl::Context *context)
 {
     const GLuint baseLevel = mState.getEffectiveBaseLevel();
     const GLuint maxLevel  = mState.getMipmapMaxLevel();
@@ -1973,24 +2026,28 @@
         {
             int faceLevelSize =
                 (std::max(mImageArray[faceIndex][baseLevel]->getWidth() >> (level - baseLevel), 1));
-            redefineImage(faceIndex, level, mImageArray[faceIndex][baseLevel]->getInternalFormat(),
-                          gl::Extents(faceLevelSize, faceLevelSize, 1), false);
+            ANGLE_TRY(redefineImage(context, faceIndex, level,
+                                    mImageArray[faceIndex][baseLevel]->getInternalFormat(),
+                                    gl::Extents(faceLevelSize, faceLevelSize, 1), false));
         }
     }
+    return gl::NoError();
 }
 
-gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureD3D_Cube::getRenderTarget(const gl::Context *context,
+                                           const gl::ImageIndex &index,
+                                           RenderTargetD3D **outRT)
 {
     ASSERT(gl::IsCubeMapTextureTarget(index.type));
 
     // ensure the underlying texture is created
-    ANGLE_TRY(ensureRenderTarget());
-    ANGLE_TRY(updateStorageFaceLevel(index.layerIndex, index.mipIndex));
+    ANGLE_TRY(ensureRenderTarget(context));
+    ANGLE_TRY(updateStorageFaceLevel(context, index.layerIndex, index.mipIndex));
 
-    return mTexStorage->getRenderTarget(index, outRT);
+    return mTexStorage->getRenderTarget(context, index, outRT);
 }
 
-gl::Error TextureD3D_Cube::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_Cube::initializeStorage(const gl::Context *context, bool renderTarget)
 {
     // Only initialize the first time this texture is used as a render target or shader resource
     if (mTexStorage)
@@ -2006,25 +2063,22 @@
 
     bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
 
-    TextureStorage *storage = nullptr;
+    TexStoragePointer storage(context);
     ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
 
-    gl::Error error = setCompleteTexStorage(storage);
-    if (error.isError())
-    {
-        SafeDelete(storage);
-        return error;
-    }
+    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+    storage.release();
 
     ASSERT(mTexStorage);
 
     // flush image data to the storage
-    ANGLE_TRY(updateStorage());
+    ANGLE_TRY(updateStorage(context));
 
     return gl::NoError();
 }
 
-gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const
+gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget,
+                                                 TexStoragePointer *outStorage) const
 {
     GLsizei size = getLevelZeroWidth();
 
@@ -2049,12 +2103,14 @@
     }
 
     // TODO (geofflang): detect if storage creation succeeded
-    *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly);
+    outStorage->reset(mRenderer->createTextureStorageCube(
+        getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly));
 
     return gl::NoError();
 }
 
-gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_Cube::setCompleteTexStorage(const gl::Context *context,
+                                                 TextureStorage *newCompleteTexStorage)
 {
     if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
     {
@@ -2063,19 +2119,19 @@
             for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
             {
                 ANGLE_TRY(mImageArray[faceIndex][level]->setManagedSurfaceCube(
-                    newCompleteTexStorage, faceIndex, level));
+                    context, newCompleteTexStorage, faceIndex, level));
             }
         }
     }
 
-    SafeDelete(mTexStorage);
+    ANGLE_TRY(releaseTexStorage(context));
     mTexStorage = newCompleteTexStorage;
 
     mDirtyImages = true;
     return gl::NoError();
 }
 
-gl::Error TextureD3D_Cube::updateStorage()
+gl::Error TextureD3D_Cube::updateStorage(const gl::Context *context)
 {
     ASSERT(mTexStorage != nullptr);
     GLint storageLevels = mTexStorage->getLevelCount();
@@ -2085,7 +2141,7 @@
         {
             if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level))
             {
-                ANGLE_TRY(updateStorageFaceLevel(face, level));
+                ANGLE_TRY(updateStorageFaceLevel(context, face, level));
             }
         }
     }
@@ -2148,7 +2204,9 @@
     return isFaceLevelComplete(index.layerIndex, index.mipIndex);
 }
 
-gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level)
+gl::Error TextureD3D_Cube::updateStorageFaceLevel(const gl::Context *context,
+                                                  int faceIndex,
+                                                  int level)
 {
     ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) &&
            mImageArray[faceIndex][level] != nullptr);
@@ -2159,17 +2217,18 @@
         GLenum faceTarget = gl::LayerIndexToCubeMapTextureTarget(faceIndex);
         gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level);
         gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1);
-        ANGLE_TRY(commitRegion(index, region));
+        ANGLE_TRY(commitRegion(context, index, region));
     }
 
     return gl::NoError();
 }
 
-void TextureD3D_Cube::redefineImage(int faceIndex,
-                                    GLint level,
-                                    GLenum internalformat,
-                                    const gl::Extents &size,
-                                    bool forceRelease)
+gl::Error TextureD3D_Cube::redefineImage(const gl::Context *context,
+                                         int faceIndex,
+                                         GLint level,
+                                         GLenum internalformat,
+                                         const gl::Extents &size,
+                                         bool forceRelease)
 {
     // If there currently is a corresponding storage texture image, it has these parameters
     const int storageWidth     = std::max(1, getLevelZeroWidth() >> level);
@@ -2189,9 +2248,11 @@
             internalformat != storageFormat)  // Discard mismatched storage
         {
             markAllImagesDirty();
-            SafeDelete(mTexStorage);
+            ANGLE_TRY(releaseTexStorage(context));
         }
     }
+
+    return gl::NoError();
 }
 
 gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const
@@ -2241,8 +2302,6 @@
     {
         delete mImageArray[i];
     }
-
-    SafeDelete(mTexStorage);
 }
 
 ImageD3D *TextureD3D_3D::getImage(int level, int layer) const
@@ -2303,7 +2362,9 @@
     return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
-gl::Error TextureD3D_3D::setEGLImageTarget(GLenum target, egl::Image *image)
+gl::Error TextureD3D_3D::setEGLImageTarget(const gl::Context *context,
+                                           GLenum target,
+                                           egl::Image *image)
 {
     UNREACHABLE();
     return gl::InternalError();
@@ -2323,8 +2384,8 @@
     const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
 
     GLint level = static_cast<GLint>(imageLevel);
-    redefineImage(level, internalFormatInfo.sizedInternalFormat, size,
-                  shouldForceReleaseImagesOnSetImage(pixels));
+    ANGLE_TRY(redefineImage(context, level, internalFormatInfo.sizedInternalFormat, size,
+                            shouldForceReleaseImagesOnSetImage(pixels)));
 
     bool fastUnpacked = false;
 
@@ -2336,7 +2397,7 @@
     {
         // Will try to create RT storage if it does not exist
         RenderTargetD3D *destRenderTarget = nullptr;
-        ANGLE_TRY(getRenderTarget(index, &destRenderTarget));
+        ANGLE_TRY(getRenderTarget(context, index, &destRenderTarget));
 
         gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
 
@@ -2351,7 +2412,7 @@
 
     if (!fastUnpacked)
     {
-        ANGLE_TRY(setImageImpl(index, type, unpack, pixels, 0));
+        ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, 0));
     }
 
     return gl::NoError();
@@ -2375,7 +2436,7 @@
     if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
     {
         RenderTargetD3D *destRenderTarget = nullptr;
-        ANGLE_TRY(getRenderTarget(index, &destRenderTarget));
+        ANGLE_TRY(getRenderTarget(context, index, &destRenderTarget));
         ASSERT(!mImageArray[level]->isDirty());
 
         return fastUnpackPixels(context, unpack, pixels, area, getInternalFormat(level), type,
@@ -2383,7 +2444,7 @@
     }
     else
     {
-        return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
+        return TextureD3D::subImage(context, index, area, format, type, unpack, pixels, 0);
     }
 }
 
@@ -2400,10 +2461,11 @@
 
     GLint level = static_cast<GLint>(imageLevel);
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
-    redefineImage(level, internalFormat, size, shouldForceReleaseImagesOnSetImage(pixels));
+    ANGLE_TRY(redefineImage(context, level, internalFormat, size,
+                            shouldForceReleaseImagesOnSetImage(pixels)));
 
     gl::ImageIndex index = gl::ImageIndex::Make3D(level);
-    return setCompressedImageImpl(index, unpack, pixels, 0);
+    return setCompressedImageImpl(context, index, unpack, pixels, 0);
 }
 
 gl::Error TextureD3D_3D::setCompressedSubImage(const gl::Context *context,
@@ -2418,8 +2480,8 @@
     ASSERT(target == GL_TEXTURE_3D);
 
     gl::ImageIndex index = gl::ImageIndex::Make3D(static_cast<GLint>(level));
-    ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0));
-    return commitRegion(index, area);
+    ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
+    return commitRegion(context, index, area);
 }
 
 gl::Error TextureD3D_3D::copyImage(const gl::Context *context,
@@ -2451,7 +2513,7 @@
 
     // if (!canCreateRenderTargetForImage(index))
     {
-        ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source));
+        ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(context, destOffset, sourceArea, source));
         mDirtyImages = true;
     }
     // else
@@ -2459,7 +2521,7 @@
     //    ANGLE_TRY(ensureRenderTarget());
     //    if (isValidLevel(level))
     //    {
-    //        ANGLE_TRY(updateStorageLevel(level));
+    //        ANGLE_TRY(updateStorageLevel(context, level));
     //        ANGLE_TRY(mRenderer->copyImage3D(
     //            source, sourceArea,
     //            gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
@@ -2493,35 +2555,34 @@
 
     // TODO(geofflang): Verify storage creation had no errors
     bool renderTarget = IsRenderTargetUsage(mState.getUsage());
-    TextureStorage *storage =
-        mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width, size.height,
-                                          size.depth, static_cast<int>(levels));
+    TexStoragePointer storage(context);
+    storage.reset(mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width,
+                                                    size.height, size.depth,
+                                                    static_cast<int>(levels)));
 
-    gl::Error error = setCompleteTexStorage(storage);
-    if (error.isError())
-    {
-        SafeDelete(storage);
-        return error;
-    }
+    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+    storage.release();
 
-    ANGLE_TRY(updateStorage());
+    ANGLE_TRY(updateStorage(context));
 
     mImmutable = true;
 
     return gl::NoError();
 }
 
-void TextureD3D_3D::bindTexImage(egl::Surface *surface)
+gl::Error TextureD3D_3D::bindTexImage(const gl::Context *context, egl::Surface *surface)
 {
     UNREACHABLE();
+    return gl::InternalError();
 }
 
-void TextureD3D_3D::releaseTexImage()
+gl::Error TextureD3D_3D::releaseTexImage(const gl::Context *context)
 {
     UNREACHABLE();
+    return gl::InternalError();
 }
 
-void TextureD3D_3D::initMipmapImages()
+gl::Error TextureD3D_3D::initMipmapImages(const gl::Context *context)
 {
     const GLuint baseLevel = mState.getEffectiveBaseLevel();
     const GLuint maxLevel  = mState.getMipmapMaxLevel();
@@ -2532,28 +2593,32 @@
         gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1),
                               std::max(getLevelZeroHeight() >> level, 1),
                               std::max(getLevelZeroDepth() >> level, 1));
-        redefineImage(level, getBaseLevelInternalFormat(), levelSize, false);
+        ANGLE_TRY(redefineImage(context, level, getBaseLevelInternalFormat(), levelSize, false));
     }
+
+    return gl::NoError();
 }
 
-gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureD3D_3D::getRenderTarget(const gl::Context *context,
+                                         const gl::ImageIndex &index,
+                                         RenderTargetD3D **outRT)
 {
     // ensure the underlying texture is created
-    ANGLE_TRY(ensureRenderTarget());
+    ANGLE_TRY(ensureRenderTarget(context));
 
     if (index.hasLayer())
     {
-        ANGLE_TRY(updateStorage());
+        ANGLE_TRY(updateStorage(context));
     }
     else
     {
-        ANGLE_TRY(updateStorageLevel(index.mipIndex));
+        ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
     }
 
-    return mTexStorage->getRenderTarget(index, outRT);
+    return mTexStorage->getRenderTarget(context, index, outRT);
 }
 
-gl::Error TextureD3D_3D::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_3D::initializeStorage(const gl::Context *context, bool renderTarget)
 {
     // Only initialize the first time this texture is used as a render target or shader resource
     if (mTexStorage)
@@ -2569,25 +2634,22 @@
 
     bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
 
-    TextureStorage *storage = nullptr;
+    TexStoragePointer storage(context);
     ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
 
-    gl::Error error = setCompleteTexStorage(storage);
-    if (error.isError())
-    {
-        SafeDelete(storage);
-        return error;
-    }
+    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+    storage.release();
 
     ASSERT(mTexStorage);
 
     // flush image data to the storage
-    ANGLE_TRY(updateStorage());
+    ANGLE_TRY(updateStorage(context));
 
     return gl::NoError();
 }
 
-gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const
+gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget,
+                                               TexStoragePointer *outStorage) const
 {
     GLsizei width         = getLevelZeroWidth();
     GLsizei height        = getLevelZeroHeight();
@@ -2600,14 +2662,16 @@
     GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth));
 
     // TODO: Verify creation of the storage succeeded
-    *outStorage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels);
+    outStorage->reset(mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height,
+                                                        depth, levels));
 
     return gl::NoError();
 }
 
-gl::Error TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_3D::setCompleteTexStorage(const gl::Context *context,
+                                               TextureStorage *newCompleteTexStorage)
 {
-    SafeDelete(mTexStorage);
+    ANGLE_TRY(releaseTexStorage(context));
     mTexStorage = newCompleteTexStorage;
     mDirtyImages = true;
 
@@ -2617,7 +2681,7 @@
     return gl::NoError();
 }
 
-gl::Error TextureD3D_3D::updateStorage()
+gl::Error TextureD3D_3D::updateStorage(const gl::Context *context)
 {
     ASSERT(mTexStorage != nullptr);
     GLint storageLevels = mTexStorage->getLevelCount();
@@ -2625,7 +2689,7 @@
     {
         if (mImageArray[level]->isDirty() && isLevelComplete(level))
         {
-            ANGLE_TRY(updateStorageLevel(level));
+            ANGLE_TRY(updateStorageLevel(context, level));
         }
     }
 
@@ -2690,7 +2754,7 @@
     return isLevelComplete(index.mipIndex);
 }
 
-gl::Error TextureD3D_3D::updateStorageLevel(int level)
+gl::Error TextureD3D_3D::updateStorageLevel(const gl::Context *context, int level)
 {
     ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != nullptr);
     ASSERT(isLevelComplete(level));
@@ -2699,16 +2763,17 @@
     {
         gl::ImageIndex index = gl::ImageIndex::Make3D(level);
         gl::Box region(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
-        ANGLE_TRY(commitRegion(index, region));
+        ANGLE_TRY(commitRegion(context, index, region));
     }
 
     return gl::NoError();
 }
 
-void TextureD3D_3D::redefineImage(GLint level,
-                                  GLenum internalformat,
-                                  const gl::Extents &size,
-                                  bool forceRelease)
+gl::Error TextureD3D_3D::redefineImage(const gl::Context *context,
+                                       GLint level,
+                                       GLenum internalformat,
+                                       const gl::Extents &size,
+                                       bool forceRelease)
 {
     // If there currently is a corresponding storage texture image, it has these parameters
     const int storageWidth  = std::max(1, getLevelZeroWidth() >> level);
@@ -2728,9 +2793,11 @@
             internalformat != storageFormat)  // Discard mismatched storage
         {
             markAllImagesDirty();
-            SafeDelete(mTexStorage);
+            ANGLE_TRY(releaseTexStorage(context));
         }
     }
+
+    return gl::NoError();
 }
 
 gl::ImageIndexIterator TextureD3D_3D::imageIterator() const
@@ -2782,7 +2849,6 @@
     // Images might be relying on the TextureStorage for some of their data.
     // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
     deleteImages();
-    SafeDelete(mTexStorage);
 }
 
 ImageD3D *TextureD3D_2DArray::getImage(int level, int layer) const
@@ -2828,7 +2894,9 @@
     return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
-gl::Error TextureD3D_2DArray::setEGLImageTarget(GLenum target, egl::Image *image)
+gl::Error TextureD3D_2DArray::setEGLImageTarget(const gl::Context *context,
+                                                GLenum target,
+                                                egl::Image *image)
 {
     UNREACHABLE();
     return gl::InternalError();
@@ -2849,8 +2917,8 @@
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
 
     GLint level = static_cast<GLint>(imageLevel);
-    redefineImage(level, formatInfo.sizedInternalFormat, size,
-                  shouldForceReleaseImagesOnSetImage(pixels));
+    ANGLE_TRY(redefineImage(context, level, formatInfo.sizedInternalFormat, size,
+                            shouldForceReleaseImagesOnSetImage(pixels)));
 
     GLsizei inputDepthPitch              = 0;
     ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment,
@@ -2861,7 +2929,7 @@
     {
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
         gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
-        ANGLE_TRY(setImageImpl(index, type, unpack, pixels, layerOffset));
+        ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, layerOffset));
     }
 
     return gl::NoError();
@@ -2893,8 +2961,8 @@
         gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
 
         gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
-        ANGLE_TRY(
-            TextureD3D::subImage(index, layerArea, format, type, unpack, pixels, layerOffset));
+        ANGLE_TRY(TextureD3D::subImage(context, index, layerArea, format, type, unpack, pixels,
+                                       layerOffset));
     }
 
     return gl::NoError();
@@ -2913,7 +2981,8 @@
 
     GLint level = static_cast<GLint>(imageLevel);
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
-    redefineImage(level, internalFormat, size, shouldForceReleaseImagesOnSetImage(pixels));
+    ANGLE_TRY(redefineImage(context, level, internalFormat, size,
+                            shouldForceReleaseImagesOnSetImage(pixels)));
 
     const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
     GLsizei inputDepthPitch              = 0;
@@ -2926,7 +2995,7 @@
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
 
         gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
-        ANGLE_TRY(setCompressedImageImpl(index, unpack, pixels, layerOffset));
+        ANGLE_TRY(setCompressedImageImpl(context, index, unpack, pixels, layerOffset));
     }
 
     return gl::NoError();
@@ -2957,9 +3026,9 @@
         gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
 
         gl::ImageIndex index = gl::ImageIndex::Make2DArray(static_cast<GLint>(level), layer);
-        ANGLE_TRY(
-            TextureD3D::subImageCompressed(index, layerArea, format, unpack, pixels, layerOffset));
-        ANGLE_TRY(commitRegion(index, layerArea));
+        ANGLE_TRY(TextureD3D::subImageCompressed(context, index, layerArea, format, unpack, pixels,
+                                                 layerOffset));
+        ANGLE_TRY(commitRegion(context, index, layerArea));
     }
 
     return gl::NoError();
@@ -2991,17 +3060,17 @@
     if (!canCreateRenderTargetForImage(index))
     {
         gl::Offset destLayerOffset(destOffset.x, destOffset.y, 0);
-        ANGLE_TRY(mImageArray[level][destOffset.z]->copyFromFramebuffer(destLayerOffset, sourceArea,
-                                                                        source));
+        ANGLE_TRY(mImageArray[level][destOffset.z]->copyFromFramebuffer(context, destLayerOffset,
+                                                                        sourceArea, source));
         mDirtyImages = true;
     }
     else
     {
-        ANGLE_TRY(ensureRenderTarget());
+        ANGLE_TRY(ensureRenderTarget(context));
 
         if (isValidLevel(level))
         {
-            ANGLE_TRY(updateStorageLevel(level));
+            ANGLE_TRY(updateStorageLevel(context, level));
             ANGLE_TRY(
                 mRenderer->copyImage2DArray(context, source, sourceArea,
                                             gl::GetUnsizedFormat(getInternalFormat(getBaseLevel())),
@@ -3044,35 +3113,34 @@
 
     // TODO(geofflang): Verify storage creation had no errors
     bool renderTarget = IsRenderTargetUsage(mState.getUsage());
-    TextureStorage *storage =
-        mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width,
-                                               size.height, size.depth, static_cast<int>(levels));
+    TexStoragePointer storage(context);
+    storage.reset(mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width,
+                                                         size.height, size.depth,
+                                                         static_cast<int>(levels)));
 
-    gl::Error error = setCompleteTexStorage(storage);
-    if (error.isError())
-    {
-        SafeDelete(storage);
-        return error;
-    }
+    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+    storage.release();
 
-    ANGLE_TRY(updateStorage());
+    ANGLE_TRY(updateStorage(context));
 
     mImmutable = true;
 
     return gl::NoError();
 }
 
-void TextureD3D_2DArray::bindTexImage(egl::Surface *surface)
+gl::Error TextureD3D_2DArray::bindTexImage(const gl::Context *context, egl::Surface *surface)
 {
     UNREACHABLE();
+    return gl::InternalError();
 }
 
-void TextureD3D_2DArray::releaseTexImage()
+gl::Error TextureD3D_2DArray::releaseTexImage(const gl::Context *context)
 {
     UNREACHABLE();
+    return gl::InternalError();
 }
 
-void TextureD3D_2DArray::initMipmapImages()
+gl::Error TextureD3D_2DArray::initMipmapImages(const gl::Context *context)
 {
     const GLuint baseLevel = mState.getEffectiveBaseLevel();
     const GLuint maxLevel  = mState.getMipmapMaxLevel();
@@ -3089,19 +3157,23 @@
         gl::Extents levelLayerSize(std::max(baseWidth >> level, 1),
                                    std::max(baseHeight >> level, 1),
                                    baseDepth);
-        redefineImage(level, baseFormat, levelLayerSize, false);
+        ANGLE_TRY(redefineImage(context, level, baseFormat, levelLayerSize, false));
     }
+
+    return gl::NoError();
 }
 
-gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureD3D_2DArray::getRenderTarget(const gl::Context *context,
+                                              const gl::ImageIndex &index,
+                                              RenderTargetD3D **outRT)
 {
     // ensure the underlying texture is created
-    ANGLE_TRY(ensureRenderTarget());
-    ANGLE_TRY(updateStorageLevel(index.mipIndex));
-    return mTexStorage->getRenderTarget(index, outRT);
+    ANGLE_TRY(ensureRenderTarget(context));
+    ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
+    return mTexStorage->getRenderTarget(context, index, outRT);
 }
 
-gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_2DArray::initializeStorage(const gl::Context *context, bool renderTarget)
 {
     // Only initialize the first time this texture is used as a render target or shader resource
     if (mTexStorage)
@@ -3117,25 +3189,22 @@
 
     bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
 
-    TextureStorage *storage = nullptr;
+    TexStoragePointer storage(context);
     ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
 
-    gl::Error error = setCompleteTexStorage(storage);
-    if (error.isError())
-    {
-        SafeDelete(storage);
-        return error;
-    }
+    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+    storage.release();
 
     ASSERT(mTexStorage);
 
     // flush image data to the storage
-    ANGLE_TRY(updateStorage());
+    ANGLE_TRY(updateStorage(context));
 
     return gl::NoError();
 }
 
-gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const
+gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget,
+                                                    TexStoragePointer *outStorage) const
 {
     GLsizei width         = getLevelZeroWidth();
     GLsizei height        = getLevelZeroHeight();
@@ -3148,14 +3217,16 @@
     GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
 
     // TODO(geofflang): Verify storage creation succeeds
-    *outStorage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels);
+    outStorage->reset(mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width,
+                                                             height, depth, levels));
 
     return gl::NoError();
 }
 
-gl::Error TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_2DArray::setCompleteTexStorage(const gl::Context *context,
+                                                    TextureStorage *newCompleteTexStorage)
 {
-    SafeDelete(mTexStorage);
+    ANGLE_TRY(releaseTexStorage(context));
     mTexStorage = newCompleteTexStorage;
     mDirtyImages = true;
 
@@ -3165,7 +3236,7 @@
     return gl::NoError();
 }
 
-gl::Error TextureD3D_2DArray::updateStorage()
+gl::Error TextureD3D_2DArray::updateStorage(const gl::Context *context)
 {
     ASSERT(mTexStorage != nullptr);
     GLint storageLevels = mTexStorage->getLevelCount();
@@ -3173,7 +3244,7 @@
     {
         if (isLevelComplete(level))
         {
-            ANGLE_TRY(updateStorageLevel(level));
+            ANGLE_TRY(updateStorageLevel(context, level));
         }
     }
 
@@ -3244,9 +3315,9 @@
     return isLevelComplete(index.mipIndex);
 }
 
-gl::Error TextureD3D_2DArray::updateStorageLevel(int level)
+gl::Error TextureD3D_2DArray::updateStorageLevel(const gl::Context *context, int level)
 {
-    ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts));
+    ASSERT(level >= 0 && level < static_cast<int>(ArraySize(mLayerCounts)));
     ASSERT(isLevelComplete(level));
 
     for (int layer = 0; layer < mLayerCounts[level]; layer++)
@@ -3256,7 +3327,7 @@
         {
             gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
             gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
-            ANGLE_TRY(commitRegion(index, region));
+            ANGLE_TRY(commitRegion(context, index, region));
         }
     }
 
@@ -3277,10 +3348,11 @@
     }
 }
 
-void TextureD3D_2DArray::redefineImage(GLint level,
-                                       GLenum internalformat,
-                                       const gl::Extents &size,
-                                       bool forceRelease)
+gl::Error TextureD3D_2DArray::redefineImage(const gl::Context *context,
+                                            GLint level,
+                                            GLenum internalformat,
+                                            const gl::Extents &size,
+                                            bool forceRelease)
 {
     // If there currently is a corresponding storage texture image, it has these parameters
     const int storageWidth  = std::max(1, getLevelZeroWidth() >> level);
@@ -3333,9 +3405,11 @@
             internalformat != storageFormat)  // Discard mismatched storage
         {
             markAllImagesDirty();
-            SafeDelete(mTexStorage);
+            ANGLE_TRY(releaseTexStorage(context));
         }
     }
+
+    return gl::NoError();
 }
 
 gl::ImageIndexIterator TextureD3D_2DArray::imageIterator() const
@@ -3385,7 +3459,6 @@
 
 TextureD3D_External::~TextureD3D_External()
 {
-    SafeDelete(mTexStorage);
 }
 
 ImageD3D *TextureD3D_External::getImage(const gl::ImageIndex &index) const
@@ -3485,13 +3558,14 @@
     return gl::InternalError();
 }
 
-gl::Error TextureD3D_External::setImageExternal(GLenum target,
+gl::Error TextureD3D_External::setImageExternal(const gl::Context *context,
+                                                GLenum target,
                                                 egl::Stream *stream,
                                                 const egl::Stream::GLTextureDescription &desc)
 {
     ASSERT(target == GL_TEXTURE_EXTERNAL_OES);
 
-    SafeDelete(mTexStorage);
+    ANGLE_TRY(releaseTexStorage(context));
 
     // If the stream is null, the external image is unbound and we release the storage
     if (stream != nullptr)
@@ -3502,36 +3576,43 @@
     return gl::NoError();
 }
 
-void TextureD3D_External::bindTexImage(egl::Surface *surface)
+gl::Error TextureD3D_External::bindTexImage(const gl::Context *context, egl::Surface *surface)
 {
     UNREACHABLE();
+    return gl::InternalError();
 }
 
-void TextureD3D_External::releaseTexImage()
+gl::Error TextureD3D_External::releaseTexImage(const gl::Context *context)
 {
     UNREACHABLE();
+    return gl::InternalError();
 }
 
-gl::Error TextureD3D_External::setEGLImageTarget(GLenum target, egl::Image *image)
+gl::Error TextureD3D_External::setEGLImageTarget(const gl::Context *context,
+                                                 GLenum target,
+                                                 egl::Image *image)
 {
     EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image);
 
     // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error.
     RenderTargetD3D *renderTargetD3D = nullptr;
-    ANGLE_TRY(eglImaged3d->getRenderTarget(&renderTargetD3D));
+    ANGLE_TRY(eglImaged3d->getRenderTarget(context, &renderTargetD3D));
 
-    SafeDelete(mTexStorage);
+    ANGLE_TRY(releaseTexStorage(context));
     mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D);
 
     return gl::NoError();
 }
 
-void TextureD3D_External::initMipmapImages()
+gl::Error TextureD3D_External::initMipmapImages(const gl::Context *context)
 {
     UNREACHABLE();
+    return gl::InternalError();
 }
 
-gl::Error TextureD3D_External::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureD3D_External::getRenderTarget(const gl::Context *context,
+                                               const gl::ImageIndex &index,
+                                               RenderTargetD3D **outRT)
 {
     UNREACHABLE();
     return gl::InternalError();
@@ -3542,7 +3623,7 @@
     return (index.mipIndex == 0) ? (mTexStorage != nullptr) : false;
 }
 
-gl::Error TextureD3D_External::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_External::initializeStorage(const gl::Context *context, bool renderTarget)
 {
     // Texture storage is created when an external image is bound
     ASSERT(mTexStorage);
@@ -3550,19 +3631,20 @@
 }
 
 gl::Error TextureD3D_External::createCompleteStorage(bool renderTarget,
-                                                     TextureStorage **outTexStorage) const
+                                                     TexStoragePointer *outStorage) const
 {
     UNREACHABLE();
     return gl::NoError();
 }
 
-gl::Error TextureD3D_External::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_External::setCompleteTexStorage(const gl::Context *context,
+                                                     TextureStorage *newCompleteTexStorage)
 {
     UNREACHABLE();
     return gl::NoError();
 }
 
-gl::Error TextureD3D_External::updateStorage()
+gl::Error TextureD3D_External::updateStorage(const gl::Context *context)
 {
     // Texture storage does not need to be updated since it is already loaded with the latest
     // external image
diff --git a/src/libANGLE/renderer/d3d/TextureD3D.h b/src/libANGLE/renderer/d3d/TextureD3D.h
index 883647e..8c1807a 100644
--- a/src/libANGLE/renderer/d3d/TextureD3D.h
+++ b/src/libANGLE/renderer/d3d/TextureD3D.h
@@ -9,10 +9,11 @@
 #ifndef LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
 #define LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
 
-#include "libANGLE/renderer/TextureImpl.h"
-#include "libANGLE/angletypes.h"
 #include "libANGLE/Constants.h"
 #include "libANGLE/Stream.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
 
 namespace gl
 {
@@ -33,7 +34,9 @@
     TextureD3D(const gl::TextureState &data, RendererD3D *renderer);
     virtual ~TextureD3D();
 
-    gl::Error getNativeTexture(TextureStorage **outStorage);
+    gl::Error onDestroy(const gl::Context *context) override;
+
+    gl::Error getNativeTexture(const gl::Context *context, TextureStorage **outStorage);
 
     bool hasDirtyImages() const { return mDirtyImages; }
     void resetDirty() { mDirtyImages = false; }
@@ -41,7 +44,9 @@
     virtual ImageD3D *getImage(const gl::ImageIndex &index) const = 0;
     virtual GLsizei getLayerCount(int level) const = 0;
 
-    gl::Error getImageAndSyncFromStorage(const gl::ImageIndex &index, ImageD3D **outImage) const;
+    gl::Error getImageAndSyncFromStorage(const gl::Context *context,
+                                         const gl::ImageIndex &index,
+                                         ImageD3D **outImage) const;
 
     GLint getBaseLevelWidth() const;
     GLint getBaseLevelHeight() const;
@@ -56,7 +61,9 @@
 
     bool isImmutable() const { return mImmutable; }
 
-    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
+    virtual gl::Error getRenderTarget(const gl::Context *context,
+                                      const gl::ImageIndex &index,
+                                      RenderTargetD3D **outRT) = 0;
 
     // Returns an iterator over all "Images" for this particular Texture.
     virtual gl::ImageIndexIterator imageIterator() const = 0;
@@ -66,35 +73,50 @@
     virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const = 0;
     virtual bool isValidIndex(const gl::ImageIndex &index) const = 0;
 
-    virtual gl::Error setImageExternal(GLenum target,
-                                       egl::Stream *stream,
-                                       const egl::Stream::GLTextureDescription &desc) override;
+    gl::Error setImageExternal(const gl::Context *context,
+                               GLenum target,
+                               egl::Stream *stream,
+                               const egl::Stream::GLTextureDescription &desc) override;
     gl::Error generateMipmap(const gl::Context *context) override;
     TextureStorage *getStorage();
     ImageD3D *getBaseLevelImage() const;
 
-    gl::Error getAttachmentRenderTarget(GLenum binding,
+    gl::Error getAttachmentRenderTarget(const gl::Context *context,
+                                        GLenum binding,
                                         const gl::ImageIndex &imageIndex,
                                         FramebufferAttachmentRenderTarget **rtOut) override;
 
-    void setBaseLevel(GLuint baseLevel) override;
+    gl::Error setBaseLevel(const gl::Context *context, GLuint baseLevel) override;
 
     void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
 
   protected:
-    gl::Error setImageImpl(const gl::ImageIndex &index,
+    gl::Error setImageImpl(const gl::Context *context,
+                           const gl::ImageIndex &index,
                            GLenum type,
                            const gl::PixelUnpackState &unpack,
                            const uint8_t *pixels,
                            ptrdiff_t layerOffset);
-    gl::Error subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type,
-                       const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset);
-    gl::Error setCompressedImageImpl(const gl::ImageIndex &index,
+    gl::Error subImage(const gl::Context *context,
+                       const gl::ImageIndex &index,
+                       const gl::Box &area,
+                       GLenum format,
+                       GLenum type,
+                       const gl::PixelUnpackState &unpack,
+                       const uint8_t *pixels,
+                       ptrdiff_t layerOffset);
+    gl::Error setCompressedImageImpl(const gl::Context *context,
+                                     const gl::ImageIndex &index,
                                      const gl::PixelUnpackState &unpack,
                                      const uint8_t *pixels,
                                      ptrdiff_t layerOffset);
-    gl::Error subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format,
-                                 const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset);
+    gl::Error subImageCompressed(const gl::Context *context,
+                                 const gl::ImageIndex &index,
+                                 const gl::Box &area,
+                                 GLenum format,
+                                 const gl::PixelUnpackState &unpack,
+                                 const uint8_t *pixels,
+                                 ptrdiff_t layerOffset);
     bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat);
     gl::Error fastUnpackPixels(const gl::Context *context,
                                const gl::PixelUnpackState &unpack,
@@ -109,16 +131,22 @@
     virtual GLint getLevelZeroDepth() const;
 
     GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const;
-    virtual void initMipmapImages() = 0;
+    virtual gl::Error initMipmapImages(const gl::Context *context) = 0;
     bool isBaseImageZeroSize() const;
     virtual bool isImageComplete(const gl::ImageIndex &index) const = 0;
 
     bool canCreateRenderTargetForImage(const gl::ImageIndex &index) const;
-    virtual gl::Error ensureRenderTarget();
+    gl::Error ensureRenderTarget(const gl::Context *context);
 
-    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const = 0;
-    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) = 0;
-    gl::Error commitRegion(const gl::ImageIndex &index, const gl::Box &region);
+    virtual gl::Error createCompleteStorage(bool renderTarget,
+                                            TexStoragePointer *outTexStorage) const = 0;
+    virtual gl::Error setCompleteTexStorage(const gl::Context *context,
+                                            TextureStorage *newCompleteTexStorage) = 0;
+    gl::Error commitRegion(const gl::Context *context,
+                           const gl::ImageIndex &index,
+                           const gl::Box &region);
+
+    gl::Error releaseTexStorage(const gl::Context *context);
 
     GLuint getBaseLevel() const { return mBaseLevel; };
 
@@ -136,9 +164,9 @@
     TextureStorage *mTexStorage;
 
   private:
-    virtual gl::Error initializeStorage(bool renderTarget) = 0;
+    virtual gl::Error initializeStorage(const gl::Context *context, bool renderTarget) = 0;
 
-    virtual gl::Error updateStorage() = 0;
+    virtual gl::Error updateStorage(const gl::Context *context) = 0;
 
     bool shouldUseSetData(const ImageD3D *image) const;
 
@@ -153,9 +181,9 @@
     TextureD3D_2D(const gl::TextureState &data, RendererD3D *renderer);
     virtual ~TextureD3D_2D();
 
-    virtual ImageD3D *getImage(int level, int layer) const;
-    virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
-    virtual GLsizei getLayerCount(int level) const;
+    ImageD3D *getImage(int level, int layer) const;
+    ImageD3D *getImage(const gl::ImageIndex &index) const override;
+    GLsizei getLayerCount(int level) const override;
 
     GLsizei getWidth(GLint level) const;
     GLsizei getHeight(GLint level) const;
@@ -238,16 +266,20 @@
                          GLenum internalFormat,
                          const gl::Extents &size) override;
 
-    virtual void bindTexImage(egl::Surface *surface);
-    virtual void releaseTexImage();
+    gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+    gl::Error releaseTexImage(const gl::Context *context) override;
 
-    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+    gl::Error setEGLImageTarget(const gl::Context *context,
+                                GLenum target,
+                                egl::Image *image) override;
 
-    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
 
-    virtual gl::ImageIndexIterator imageIterator() const;
-    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
-    virtual bool isValidIndex(const gl::ImageIndex &index) const;
+    gl::ImageIndexIterator imageIterator() const override;
+    gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+    bool isValidIndex(const gl::ImageIndex &index) const override;
 
     gl::Error setStorageMultisample(const gl::Context *context,
                                     GLenum target,
@@ -260,23 +292,26 @@
     void markAllImagesDirty() override;
 
   private:
-    virtual gl::Error initializeStorage(bool renderTarget);
-    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const;
-    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+    gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override;
+    gl::Error createCompleteStorage(bool renderTarget,
+                                    TexStoragePointer *outTexStorage) const override;
+    gl::Error setCompleteTexStorage(const gl::Context *context,
+                                    TextureStorage *newCompleteTexStorage) override;
 
-    virtual gl::Error updateStorage();
-    virtual void initMipmapImages();
+    gl::Error updateStorage(const gl::Context *context) override;
+    gl::Error initMipmapImages(const gl::Context *context) override;
 
     bool isValidLevel(int level) const;
     bool isLevelComplete(int level) const;
     virtual bool isImageComplete(const gl::ImageIndex &index) const;
 
-    gl::Error updateStorageLevel(int level);
+    gl::Error updateStorageLevel(const gl::Context *context, int level);
 
-    void redefineImage(size_t level,
-                       GLenum internalformat,
-                       const gl::Extents &size,
-                       bool forceRelease);
+    gl::Error redefineImage(const gl::Context *context,
+                            size_t level,
+                            GLenum internalformat,
+                            const gl::Extents &size,
+                            bool forceRelease);
 
     bool mEGLImageTarget;
     ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
@@ -288,12 +323,9 @@
     TextureD3D_Cube(const gl::TextureState &data, RendererD3D *renderer);
     virtual ~TextureD3D_Cube();
 
-    virtual ImageD3D *getImage(int level, int layer) const;
-    virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
-    virtual GLsizei getLayerCount(int level) const;
-
-    virtual bool hasDirtyImages() const { return mDirtyImages; }
-    virtual void resetDirty() { mDirtyImages = false; }
+    ImageD3D *getImage(int level, int layer) const;
+    ImageD3D *getImage(const gl::ImageIndex &index) const override;
+    GLsizei getLayerCount(int level) const override;
 
     GLenum getInternalFormat(GLint level, GLint layer) const;
     bool isDepth(GLint level, GLint layer) const;
@@ -373,39 +405,46 @@
                          GLenum internalFormat,
                          const gl::Extents &size) override;
 
-    virtual void bindTexImage(egl::Surface *surface);
-    virtual void releaseTexImage();
+    gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+    gl::Error releaseTexImage(const gl::Context *context) override;
 
-    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+    gl::Error setEGLImageTarget(const gl::Context *context,
+                                GLenum target,
+                                egl::Image *image) override;
 
-    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
 
-    virtual gl::ImageIndexIterator imageIterator() const;
-    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
-    virtual bool isValidIndex(const gl::ImageIndex &index) const;
+    gl::ImageIndexIterator imageIterator() const override;
+    gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+    bool isValidIndex(const gl::ImageIndex &index) const override;
 
   protected:
     void markAllImagesDirty() override;
 
   private:
-    virtual gl::Error initializeStorage(bool renderTarget);
-    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const;
-    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+    gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override;
+    gl::Error createCompleteStorage(bool renderTarget,
+                                    TexStoragePointer *outTexStorage) const override;
+    gl::Error setCompleteTexStorage(const gl::Context *context,
+                                    TextureStorage *newCompleteTexStorage) override;
 
-    virtual gl::Error updateStorage();
-    void initMipmapImages() override;
+    gl::Error updateStorage(const gl::Context *context) override;
+    gl::Error initMipmapImages(const gl::Context *context) override;
 
     bool isValidFaceLevel(int faceIndex, int level) const;
     bool isFaceLevelComplete(int faceIndex, int level) const;
     bool isCubeComplete() const;
     virtual bool isImageComplete(const gl::ImageIndex &index) const;
-    gl::Error updateStorageFaceLevel(int faceIndex, int level);
+    gl::Error updateStorageFaceLevel(const gl::Context *context, int faceIndex, int level);
 
-    void redefineImage(int faceIndex,
-                       GLint level,
-                       GLenum internalformat,
-                       const gl::Extents &size,
-                       bool forceRelease);
+    gl::Error redefineImage(const gl::Context *context,
+                            int faceIndex,
+                            GLint level,
+                            GLenum internalformat,
+                            const gl::Extents &size,
+                            bool forceRelease);
 
     ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
 };
@@ -416,9 +455,9 @@
     TextureD3D_3D(const gl::TextureState &data, RendererD3D *renderer);
     virtual ~TextureD3D_3D();
 
-    virtual ImageD3D *getImage(int level, int layer) const;
-    virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
-    virtual GLsizei getLayerCount(int level) const;
+    ImageD3D *getImage(int level, int layer) const;
+    ImageD3D *getImage(const gl::ImageIndex &index) const override;
+    GLsizei getLayerCount(int level) const override;
 
     GLsizei getWidth(GLint level) const;
     GLsizei getHeight(GLint level) const;
@@ -480,38 +519,45 @@
                          GLenum internalFormat,
                          const gl::Extents &size) override;
 
-    virtual void bindTexImage(egl::Surface *surface);
-    virtual void releaseTexImage();
+    gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+    gl::Error releaseTexImage(const gl::Context *context) override;
 
-    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+    gl::Error setEGLImageTarget(const gl::Context *context,
+                                GLenum target,
+                                egl::Image *image) override;
 
-    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
 
-    virtual gl::ImageIndexIterator imageIterator() const;
-    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
-    virtual bool isValidIndex(const gl::ImageIndex &index) const;
+    gl::ImageIndexIterator imageIterator() const override;
+    gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+    bool isValidIndex(const gl::ImageIndex &index) const override;
 
   protected:
     void markAllImagesDirty() override;
     GLint getLevelZeroDepth() const override;
 
   private:
-    virtual gl::Error initializeStorage(bool renderTarget);
-    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const;
-    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+    gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override;
+    gl::Error createCompleteStorage(bool renderTarget,
+                                    TexStoragePointer *outStorage) const override;
+    gl::Error setCompleteTexStorage(const gl::Context *context,
+                                    TextureStorage *newCompleteTexStorage) override;
 
-    virtual gl::Error updateStorage();
-    void initMipmapImages() override;
+    gl::Error updateStorage(const gl::Context *context) override;
+    gl::Error initMipmapImages(const gl::Context *context) override;
 
     bool isValidLevel(int level) const;
     bool isLevelComplete(int level) const;
     virtual bool isImageComplete(const gl::ImageIndex &index) const;
-    gl::Error updateStorageLevel(int level);
+    gl::Error updateStorageLevel(const gl::Context *context, int level);
 
-    void redefineImage(GLint level,
-                       GLenum internalformat,
-                       const gl::Extents &size,
-                       bool forceRelease);
+    gl::Error redefineImage(const gl::Context *context,
+                            GLint level,
+                            GLenum internalformat,
+                            const gl::Extents &size,
+                            bool forceRelease);
 
     ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
 };
@@ -585,38 +631,45 @@
                          GLenum internalFormat,
                          const gl::Extents &size) override;
 
-    virtual void bindTexImage(egl::Surface *surface);
-    virtual void releaseTexImage();
+    gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+    gl::Error releaseTexImage(const gl::Context *context) override;
 
-    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+    gl::Error setEGLImageTarget(const gl::Context *context,
+                                GLenum target,
+                                egl::Image *image) override;
 
-    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
 
-    virtual gl::ImageIndexIterator imageIterator() const;
-    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
-    virtual bool isValidIndex(const gl::ImageIndex &index) const;
+    gl::ImageIndexIterator imageIterator() const override;
+    gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+    bool isValidIndex(const gl::ImageIndex &index) const override;
 
   protected:
     void markAllImagesDirty() override;
 
   private:
-    virtual gl::Error initializeStorage(bool renderTarget);
-    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const;
-    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+    gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override;
+    gl::Error createCompleteStorage(bool renderTarget,
+                                    TexStoragePointer *outStorage) const override;
+    gl::Error setCompleteTexStorage(const gl::Context *context,
+                                    TextureStorage *newCompleteTexStorage) override;
 
-    virtual gl::Error updateStorage();
-    void initMipmapImages() override;
+    gl::Error updateStorage(const gl::Context *context) override;
+    gl::Error initMipmapImages(const gl::Context *context) override;
 
     bool isValidLevel(int level) const;
     bool isLevelComplete(int level) const;
     virtual bool isImageComplete(const gl::ImageIndex &index) const;
-    gl::Error updateStorageLevel(int level);
+    gl::Error updateStorageLevel(const gl::Context *context, int level);
 
     void deleteImages();
-    void redefineImage(GLint level,
-                       GLenum internalformat,
-                       const gl::Extents &size,
-                       bool forceRelease);
+    gl::Error redefineImage(const gl::Context *context,
+                            GLint level,
+                            GLenum internalformat,
+                            const gl::Extents &size,
+                            bool forceRelease);
 
     // Storing images as an array of single depth textures since D3D11 treats each array level of a
     // Texture2D object as a separate subresource.  Each layer would have to be looped over
@@ -689,16 +742,21 @@
                          GLenum internalFormat,
                          const gl::Extents &size) override;
 
-    gl::Error setImageExternal(GLenum target,
+    gl::Error setImageExternal(const gl::Context *context,
+                               GLenum target,
                                egl::Stream *stream,
                                const egl::Stream::GLTextureDescription &desc) override;
 
-    void bindTexImage(egl::Surface *surface) override;
-    void releaseTexImage() override;
+    gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+    gl::Error releaseTexImage(const gl::Context *context) override;
 
-    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+    gl::Error setEGLImageTarget(const gl::Context *context,
+                                GLenum target,
+                                egl::Image *image) override;
 
-    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
 
     gl::ImageIndexIterator imageIterator() const override;
     gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
@@ -708,13 +766,14 @@
     void markAllImagesDirty() override;
 
   private:
-    gl::Error initializeStorage(bool renderTarget) override;
+    gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override;
     gl::Error createCompleteStorage(bool renderTarget,
-                                    TextureStorage **outTexStorage) const override;
-    gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) override;
+                                    TexStoragePointer *outTexStorage) const override;
+    gl::Error setCompleteTexStorage(const gl::Context *context,
+                                    TextureStorage *newCompleteTexStorage) override;
 
-    gl::Error updateStorage() override;
-    void initMipmapImages() override;
+    gl::Error updateStorage(const gl::Context *context) override;
+    gl::Error initMipmapImages(const gl::Context *context) override;
 
     bool isImageComplete(const gl::ImageIndex &index) const override;
 };
@@ -780,16 +839,21 @@
                          GLenum internalFormat,
                          const gl::Extents &size) override;
 
-    gl::Error setImageExternal(GLenum target,
+    gl::Error setImageExternal(const gl::Context *context,
+                               GLenum target,
                                egl::Stream *stream,
                                const egl::Stream::GLTextureDescription &desc) override;
 
-    void bindTexImage(egl::Surface *surface) override;
-    void releaseTexImage() override;
+    gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+    gl::Error releaseTexImage(const gl::Context *context) override;
 
-    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+    gl::Error setEGLImageTarget(const gl::Context *context,
+                                GLenum target,
+                                egl::Image *image) override;
 
-    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
 
     gl::ImageIndexIterator imageIterator() const override;
     gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
@@ -801,13 +865,14 @@
     void markAllImagesDirty() override;
 
   private:
-    gl::Error initializeStorage(bool renderTarget) override;
+    gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override;
     gl::Error createCompleteStorage(bool renderTarget,
-                                    TextureStorage **outTexStorage) const override;
-    gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) override;
+                                    TexStoragePointer *outTexStorage) const override;
+    gl::Error setCompleteTexStorage(const gl::Context *context,
+                                    TextureStorage *newCompleteTexStorage) override;
 
-    gl::Error updateStorage() override;
-    void initMipmapImages() override;
+    gl::Error updateStorage(const gl::Context *context) override;
+    gl::Error initMipmapImages(const gl::Context *context) override;
 
     bool isImageComplete(const gl::ImageIndex &index) const override;
 };
diff --git a/src/libANGLE/renderer/d3d/TextureStorage.h b/src/libANGLE/renderer/d3d/TextureStorage.h
index f643cf9..239ac54 100644
--- a/src/libANGLE/renderer/d3d/TextureStorage.h
+++ b/src/libANGLE/renderer/d3d/TextureStorage.h
@@ -23,7 +23,7 @@
 struct ImageIndex;
 struct Box;
 struct PixelUnpackState;
-}
+}  // namespace gl
 
 namespace rx
 {
@@ -35,7 +35,12 @@
 {
   public:
     TextureStorage() {}
-    virtual ~TextureStorage() {}
+
+    virtual gl::Error onDestroy(const gl::Context *context)
+    {
+        delete this;
+        return gl::NoError();
+    }
 
     virtual int getTopLevel() const = 0;
     virtual bool isRenderTarget() const = 0;
@@ -43,22 +48,34 @@
     virtual bool supportsNativeMipmapFunction() const = 0;
     virtual int getLevelCount() const = 0;
 
-    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
+    virtual gl::Error getRenderTarget(const gl::Context *context,
+                                      const gl::ImageIndex &index,
+                                      RenderTargetD3D **outRT) = 0;
     virtual gl::Error generateMipmap(const gl::Context *context,
                                      const gl::ImageIndex &sourceIndex,
                                      const gl::ImageIndex &destIndex) = 0;
 
-    virtual gl::Error copyToStorage(TextureStorage *destStorage) = 0;
-    virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
-                              const gl::PixelUnpackState &unpack, const uint8_t *pixelData) = 0;
+    virtual gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) = 0;
+    virtual gl::Error setData(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              ImageD3D *image,
+                              const gl::Box *destBox,
+                              GLenum type,
+                              const gl::PixelUnpackState &unpack,
+                              const uint8_t *pixelData) = 0;
 
     // This is a no-op for most implementations of TextureStorage. Some (e.g. TextureStorage11_2D) might override it.
     virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture)
     {
         return gl::NoError();
     }
+
+  protected:
+    virtual ~TextureStorage() {}
 };
 
-}
+using TexStoragePointer = angle::UniqueObjectPointer<TextureStorage, gl::Context>;
+
+}  // namespace rx
 
 #endif // LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
diff --git a/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
index bc6c763..fc57957 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
@@ -1969,6 +1969,8 @@
 gl::ErrorOrResult<TextureHelper11> Blit11::resolveDepth(const gl::Context *context,
                                                         RenderTarget11 *depth)
 {
+    ANGLE_TRY(initResources());
+
     // Multisampled depth stencil SRVs are not available in feature level 10.0
     ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
 
@@ -2100,6 +2102,8 @@
                                                           RenderTarget11 *depthStencil,
                                                           bool alsoDepth)
 {
+    ANGLE_TRY(initResources());
+
     // Multisampled depth stencil SRVs are not available in feature level 10.0
     ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
 
diff --git a/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
index aaea7ab..69a82d0 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
@@ -230,7 +230,8 @@
                   uint8_t **mapPointerOut) override;
     void unmap() override;
 
-    gl::Error packPixels(const gl::FramebufferAttachment &readAttachment,
+    gl::Error packPixels(const gl::Context *context,
+                         const gl::FramebufferAttachment &readAttachment,
                          const PackPixelsParams &params);
 
   private:
@@ -662,7 +663,8 @@
     return nativeStorage->getSRVForFormat(srvFormat);
 }
 
-gl::Error Buffer11::packPixels(const gl::FramebufferAttachment &readAttachment,
+gl::Error Buffer11::packPixels(const gl::Context *context,
+                               const gl::FramebufferAttachment &readAttachment,
                                const PackPixelsParams &params)
 {
     PackStorage *packStorage = nullptr;
@@ -672,7 +674,7 @@
     ANGLE_TRY_RESULT(getLatestBufferStorage(), latestStorage);
 
     ASSERT(packStorage);
-    ANGLE_TRY(packStorage->packPixels(readAttachment, params));
+    ANGLE_TRY(packStorage->packPixels(context, readAttachment, params));
     packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1);
 
     return gl::NoError();
@@ -1421,19 +1423,20 @@
     // No-op
 }
 
-gl::Error Buffer11::PackStorage::packPixels(const gl::FramebufferAttachment &readAttachment,
+gl::Error Buffer11::PackStorage::packPixels(const gl::Context *context,
+                                            const gl::FramebufferAttachment &readAttachment,
                                             const PackPixelsParams &params)
 {
     ANGLE_TRY(flushQueuedPackCommand());
 
     RenderTarget11 *renderTarget = nullptr;
-    ANGLE_TRY(readAttachment.getRenderTarget(&renderTarget));
+    ANGLE_TRY(readAttachment.getRenderTarget(context, &renderTarget));
 
     const TextureHelper11 &srcTexture = renderTarget->getTexture();
     ASSERT(srcTexture.valid());
     unsigned int srcSubresource = renderTarget->getSubresourceIndex();
 
-    mQueuedPackCommand.reset(new PackPixelsParams(params));
+    mQueuedPackCommand.reset(new PackPixelsParams(context, params));
 
     gl::Extents srcTextureSize(params.area.width, params.area.height, 1);
     if (!mStagingTexture.get() || mStagingTexture.getFormat() != srcTexture.getFormat() ||
diff --git a/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
index 4ae869d..65fded2 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
@@ -64,7 +64,8 @@
                                      UINT *numConstantsOut);
     gl::ErrorOrResult<ID3D11ShaderResourceView *> getSRV(DXGI_FORMAT srvFormat);
     bool isMapped() const { return mMappedStorage != nullptr; }
-    gl::Error packPixels(const gl::FramebufferAttachment &readAttachment,
+    gl::Error packPixels(const gl::Context *context,
+                         const gl::FramebufferAttachment &readAttachment,
                          const PackPixelsParams &params);
     size_t getTotalCPUBufferMemoryBytes() const;
 
diff --git a/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
index 5898f80..82076c7 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
@@ -406,7 +406,7 @@
         }
 
         RenderTarget11 *renderTarget = nullptr;
-        ANGLE_TRY(attachment.getRenderTarget(&renderTarget));
+        ANGLE_TRY(attachment.getRenderTarget(context, &renderTarget));
 
         const gl::InternalFormat &formatInfo = *attachment.getFormat().info;
 
@@ -516,7 +516,7 @@
         RenderTarget11 *depthStencilRenderTarget = nullptr;
 
         ASSERT(depthStencilAttachment != nullptr);
-        ANGLE_TRY(depthStencilAttachment->getRenderTarget(&depthStencilRenderTarget));
+        ANGLE_TRY(depthStencilAttachment->getRenderTarget(context, &depthStencilRenderTarget));
 
         dsv = depthStencilRenderTarget->getDepthStencilView().get();
         ASSERT(dsv != nullptr);
diff --git a/src/libANGLE/renderer/d3d/d3d11/Context11.cpp b/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
index cc46e43..91a3622 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
@@ -265,9 +265,9 @@
     return mRenderer->getTimestamp();
 }
 
-void Context11::onMakeCurrent(const gl::ContextState &data)
+void Context11::onMakeCurrent(const gl::Context *context)
 {
-    mRenderer->getStateManager()->onMakeCurrent(data);
+    mRenderer->getStateManager()->onMakeCurrent(context);
 }
 
 const gl::Caps &Context11::getNativeCaps() const
diff --git a/src/libANGLE/renderer/d3d/d3d11/Context11.h b/src/libANGLE/renderer/d3d/d3d11/Context11.h
index 291f422..f11c533 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Context11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Context11.h
@@ -123,7 +123,7 @@
     GLint64 getTimestamp() override;
 
     // Context switching
-    void onMakeCurrent(const gl::ContextState &data) override;
+    void onMakeCurrent(const gl::Context *context) override;
 
     // Caps queries
     const gl::Caps &getNativeCaps() const override;
diff --git a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
index 2dc1d6d..833d237 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
@@ -29,7 +29,8 @@
 
 namespace
 {
-gl::Error MarkAttachmentsDirty(const gl::FramebufferAttachment *attachment)
+gl::Error MarkAttachmentsDirty(const gl::Context *context,
+                               const gl::FramebufferAttachment *attachment)
 {
     if (attachment && attachment->type() == GL_TEXTURE)
     {
@@ -38,7 +39,7 @@
         TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
 
         TextureStorage *texStorage = nullptr;
-        ANGLE_TRY(textureD3D->getNativeTexture(&texStorage));
+        ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage));
 
         if (texStorage)
         {
@@ -52,14 +53,15 @@
     return gl::NoError();
 }
 
-void UpdateCachedRenderTarget(const gl::FramebufferAttachment *attachment,
+void UpdateCachedRenderTarget(const gl::Context *context,
+                              const gl::FramebufferAttachment *attachment,
                               RenderTarget11 *&cachedRenderTarget,
                               OnRenderTargetDirtyBinding *channelBinding)
 {
     RenderTarget11 *newRenderTarget = nullptr;
     if (attachment)
     {
-        attachment->getRenderTarget(&newRenderTarget);
+        attachment->getRenderTarget(context, &newRenderTarget);
     }
     if (newRenderTarget != cachedRenderTarget)
     {
@@ -88,18 +90,18 @@
 {
 }
 
-gl::Error Framebuffer11::markAttachmentsDirty() const
+gl::Error Framebuffer11::markAttachmentsDirty(const gl::Context *context) const
 {
     for (const auto &colorAttachment : mState.getColorAttachments())
     {
         if (colorAttachment.isAttached())
         {
-            ANGLE_TRY(MarkAttachmentsDirty(&colorAttachment));
+            ANGLE_TRY(MarkAttachmentsDirty(context, &colorAttachment));
         }
     }
 
-    ANGLE_TRY(MarkAttachmentsDirty(mState.getDepthAttachment()));
-    ANGLE_TRY(MarkAttachmentsDirty(mState.getStencilAttachment()));
+    ANGLE_TRY(MarkAttachmentsDirty(context, mState.getDepthAttachment()));
+    ANGLE_TRY(MarkAttachmentsDirty(context, mState.getStencilAttachment()));
 
     return gl::NoError();
 }
@@ -127,22 +129,29 @@
         ANGLE_TRY(clearer->clearFramebuffer(context, clearParams, mState));
     }
 
-    ANGLE_TRY(markAttachmentsDirty());
+    ANGLE_TRY(markAttachmentsDirty(context));
 
     return gl::NoError();
 }
 
-gl::Error Framebuffer11::invalidate(size_t count, const GLenum *attachments)
+gl::Error Framebuffer11::invalidate(const gl::Context *context,
+                                    size_t count,
+                                    const GLenum *attachments)
 {
-    return invalidateBase(count, attachments, false);
+    return invalidateBase(context, count, attachments, false);
 }
 
-gl::Error Framebuffer11::discard(size_t count, const GLenum *attachments)
+gl::Error Framebuffer11::discard(const gl::Context *context,
+                                 size_t count,
+                                 const GLenum *attachments)
 {
-    return invalidateBase(count, attachments, true);
+    return invalidateBase(context, count, attachments, true);
 }
 
-gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const
+gl::Error Framebuffer11::invalidateBase(const gl::Context *context,
+                                        size_t count,
+                                        const GLenum *attachments,
+                                        bool useEXTBehavior) const
 {
     ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
 
@@ -183,7 +192,7 @@
                 auto colorAttachment = mState.getColorAttachment(colorIndex);
                 if (colorAttachment)
                 {
-                    ANGLE_TRY(invalidateAttachment(colorAttachment));
+                    ANGLE_TRY(invalidateAttachment(context, colorAttachment));
                 }
                 break;
             }
@@ -216,31 +225,35 @@
 
     if (discardDepth && mState.getDepthAttachment())
     {
-        ANGLE_TRY(invalidateAttachment(mState.getDepthAttachment()));
+        ANGLE_TRY(invalidateAttachment(context, mState.getDepthAttachment()));
     }
 
     if (discardStencil && mState.getStencilAttachment())
     {
-        ANGLE_TRY(invalidateAttachment(mState.getStencilAttachment()));
+        ANGLE_TRY(invalidateAttachment(context, mState.getStencilAttachment()));
     }
 
     return gl::NoError();
 }
 
-gl::Error Framebuffer11::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
+gl::Error Framebuffer11::invalidateSub(const gl::Context *context,
+                                       size_t,
+                                       const GLenum *,
+                                       const gl::Rectangle &)
 {
     // A no-op implementation conforms to the spec, so don't call UNIMPLEMENTED()
     return gl::NoError();
 }
 
-gl::Error Framebuffer11::invalidateAttachment(const gl::FramebufferAttachment *attachment) const
+gl::Error Framebuffer11::invalidateAttachment(const gl::Context *context,
+                                              const gl::FramebufferAttachment *attachment) const
 {
     ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
     ASSERT(deviceContext1);
     ASSERT(attachment && attachment->isAttached());
 
     RenderTarget11 *renderTarget = nullptr;
-    ANGLE_TRY(attachment->getRenderTarget(&renderTarget));
+    ANGLE_TRY(attachment->getRenderTarget(context, &renderTarget));
     const auto &rtv = renderTarget->getRenderTargetView();
 
     if (rtv.valid())
@@ -251,7 +264,8 @@
     return gl::NoError();
 }
 
-gl::Error Framebuffer11::readPixelsImpl(const gl::Rectangle &area,
+gl::Error Framebuffer11::readPixelsImpl(const gl::Context *context,
+                                        const gl::Rectangle &area,
                                         GLenum format,
                                         GLenum type,
                                         size_t outputPitch,
@@ -268,10 +282,10 @@
         PackPixelsParams packParams(area, format, type, static_cast<GLuint>(outputPitch), pack,
                                     reinterpret_cast<ptrdiff_t>(pixels));
 
-        return packBufferStorage->packPixels(*readAttachment, packParams);
+        return packBufferStorage->packPixels(context, *readAttachment, packParams);
     }
 
-    return mRenderer->readFromAttachment(*readAttachment, area, format, type,
+    return mRenderer->readFromAttachment(context, *readAttachment, area, format, type,
                                          static_cast<GLuint>(outputPitch), pack, pixels);
 }
 
@@ -291,7 +305,7 @@
         ASSERT(readBuffer);
 
         RenderTargetD3D *readRenderTarget = nullptr;
-        ANGLE_TRY(readBuffer->getRenderTarget(&readRenderTarget));
+        ANGLE_TRY(readBuffer->getRenderTarget(context, &readRenderTarget));
         ASSERT(readRenderTarget);
 
         const auto &colorAttachments = mState.getColorAttachments();
@@ -305,7 +319,7 @@
                 drawBufferStates[colorAttachment] != GL_NONE)
             {
                 RenderTargetD3D *drawRenderTarget = nullptr;
-                ANGLE_TRY(drawBuffer.getRenderTarget(&drawRenderTarget));
+                ANGLE_TRY(drawBuffer.getRenderTarget(context, &drawRenderTarget));
                 ASSERT(drawRenderTarget);
 
                 const bool invertColorSource   = UsePresentPathFast(mRenderer, readBuffer);
@@ -339,14 +353,14 @@
         ASSERT(readBuffer);
 
         RenderTargetD3D *readRenderTarget = nullptr;
-        ANGLE_TRY(readBuffer->getRenderTarget(&readRenderTarget));
+        ANGLE_TRY(readBuffer->getRenderTarget(context, &readRenderTarget));
         ASSERT(readRenderTarget);
 
         const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
         ASSERT(drawBuffer);
 
         RenderTargetD3D *drawRenderTarget = nullptr;
-        ANGLE_TRY(drawBuffer->getRenderTarget(&drawRenderTarget));
+        ANGLE_TRY(drawBuffer->getRenderTarget(context, &drawRenderTarget));
         ASSERT(drawRenderTarget);
 
         ANGLE_TRY(mRenderer->blitRenderbufferRect(context, sourceArea, destArea, readRenderTarget,
@@ -354,7 +368,7 @@
                                                   blitDepth, blitStencil));
     }
 
-    ANGLE_TRY(markAttachmentsDirty());
+    ANGLE_TRY(markAttachmentsDirty(context));
     return gl::NoError();
 }
 
@@ -364,17 +378,17 @@
     return renderTarget11->getFormatSet().format().fboImplementationInternalFormat;
 }
 
-void Framebuffer11::updateColorRenderTarget(size_t colorIndex)
+void Framebuffer11::updateColorRenderTarget(const gl::Context *context, size_t colorIndex)
 {
-    UpdateCachedRenderTarget(mState.getColorAttachment(colorIndex),
+    UpdateCachedRenderTarget(context, mState.getColorAttachment(colorIndex),
                              mCachedColorRenderTargets[colorIndex],
                              &mColorRenderTargetsDirty[colorIndex]);
 }
 
-void Framebuffer11::updateDepthStencilRenderTarget()
+void Framebuffer11::updateDepthStencilRenderTarget(const gl::Context *context)
 {
-    UpdateCachedRenderTarget(mState.getDepthOrStencilAttachment(), mCachedDepthStencilRenderTarget,
-                             &mDepthStencilRenderTargetDirty);
+    UpdateCachedRenderTarget(context, mState.getDepthOrStencilAttachment(),
+                             mCachedDepthStencilRenderTarget, &mDepthStencilRenderTargetDirty);
 }
 
 void Framebuffer11::syncState(const gl::Context *context,
@@ -391,7 +405,7 @@
         {
             case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
             case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
-                updateDepthStencilRenderTarget();
+                updateDepthStencilRenderTarget(context);
                 break;
             case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
             case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
@@ -402,7 +416,7 @@
                        dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
                 size_t colorIndex =
                     static_cast<size_t>(dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
-                updateColorRenderTarget(colorIndex);
+                updateColorRenderTarget(context, colorIndex);
                 break;
             }
         }
diff --git a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
index bd6c9e7..f7d241c 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
@@ -23,12 +23,17 @@
     Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer);
     virtual ~Framebuffer11();
 
-    gl::Error discard(size_t count, const GLenum *attachments) override;
-    gl::Error invalidate(size_t count, const GLenum *attachments) override;
-    gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
+    gl::Error discard(const gl::Context *context, size_t count, const GLenum *attachments) override;
+    gl::Error invalidate(const gl::Context *context,
+                         size_t count,
+                         const GLenum *attachments) override;
+    gl::Error invalidateSub(const gl::Context *context,
+                            size_t count,
+                            const GLenum *attachments,
+                            const gl::Rectangle &area) override;
 
     // Invalidate the cached swizzles of all bound texture attachments.
-    gl::Error markAttachmentsDirty() const;
+    gl::Error markAttachmentsDirty(const gl::Context *context) const;
 
     void syncState(const gl::Context *context,
                    const gl::Framebuffer::DirtyBits &dirtyBits) override;
@@ -52,7 +57,8 @@
   private:
     gl::Error clearImpl(const gl::Context *context, const ClearParameters &clearParams) override;
 
-    gl::Error readPixelsImpl(const gl::Rectangle &area,
+    gl::Error readPixelsImpl(const gl::Context *context,
+                             const gl::Rectangle &area,
                              GLenum format,
                              GLenum type,
                              size_t outputPitch,
@@ -69,13 +75,17 @@
                        GLenum filter,
                        const gl::Framebuffer *sourceFramebuffer) override;
 
-    gl::Error invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const;
-    gl::Error invalidateAttachment(const gl::FramebufferAttachment *attachment) const;
+    gl::Error invalidateBase(const gl::Context *context,
+                             size_t count,
+                             const GLenum *attachments,
+                             bool useEXTBehavior) const;
+    gl::Error invalidateAttachment(const gl::Context *context,
+                                   const gl::FramebufferAttachment *attachment) const;
 
     GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
 
-    void updateColorRenderTarget(size_t colorIndex);
-    void updateDepthStencilRenderTarget();
+    void updateColorRenderTarget(const gl::Context *context, size_t colorIndex);
+    void updateDepthStencilRenderTarget(const gl::Context *context);
 
     Renderer11 *const mRenderer;
     RenderTargetArray mCachedColorRenderTargets;
diff --git a/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
index 605f1b1..85833cb 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -85,7 +85,9 @@
     releaseStagingTexture();
 }
 
-gl::Error Image11::generateMipmap(Image11 *dest,
+// static
+gl::Error Image11::GenerateMipmap(const gl::Context *context,
+                                  Image11 *dest,
                                   Image11 *src,
                                   const Renderer11DeviceCaps &rendererCaps)
 {
@@ -94,10 +96,10 @@
     ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight());
 
     D3D11_MAPPED_SUBRESOURCE destMapped;
-    ANGLE_TRY(dest->map(D3D11_MAP_WRITE, &destMapped));
+    ANGLE_TRY(dest->map(context, D3D11_MAP_WRITE, &destMapped));
 
     D3D11_MAPPED_SUBRESOURCE srcMapped;
-    gl::Error error = src->map(D3D11_MAP_READ, &srcMapped);
+    gl::Error error = src->map(context, D3D11_MAP_READ, &srcMapped);
     if (error.isError())
     {
         dest->unmap();
@@ -121,7 +123,9 @@
     return gl::NoError();
 }
 
-gl::Error Image11::copyImage(Image11 *dest,
+// static
+gl::Error Image11::CopyImage(const gl::Context *context,
+                             Image11 *dest,
                              Image11 *source,
                              const gl::Rectangle &sourceRect,
                              const gl::Offset &destOffset,
@@ -131,10 +135,10 @@
                              const Renderer11DeviceCaps &rendererCaps)
 {
     D3D11_MAPPED_SUBRESOURCE destMapped;
-    ANGLE_TRY(dest->map(D3D11_MAP_WRITE, &destMapped));
+    ANGLE_TRY(dest->map(context, D3D11_MAP_WRITE, &destMapped));
 
     D3D11_MAPPED_SUBRESOURCE srcMapped;
-    gl::Error error = source->map(D3D11_MAP_READ, &srcMapped);
+    gl::Error error = source->map(context, D3D11_MAP_READ, &srcMapped);
     if (error.isError())
     {
         dest->unmap();
@@ -232,7 +236,8 @@
     return mDirty;
 }
 
-gl::Error Image11::copyToStorage(TextureStorage *storage,
+gl::Error Image11::copyToStorage(const gl::Context *context,
+                                 TextureStorage *storage,
                                  const gl::ImageIndex &index,
                                  const gl::Box &region)
 {
@@ -248,14 +253,14 @@
     {
         // If another image is relying on this Storage for its data, then we must let it recover its
         // data before we overwrite it.
-        ANGLE_TRY(storage11->releaseAssociatedImage(index, this));
+        ANGLE_TRY(storage11->releaseAssociatedImage(context, index, this));
     }
 
     const TextureHelper11 *stagingTexture = nullptr;
     unsigned int stagingSubresourceIndex = 0;
     ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex));
-    ANGLE_TRY(
-        storage11->updateSubresourceLevel(*stagingTexture, stagingSubresourceIndex, index, region));
+    ANGLE_TRY(storage11->updateSubresourceLevel(context, *stagingTexture, stagingSubresourceIndex,
+                                                index, region));
 
     // Once the image data has been copied into the Storage, we can release it locally.
     if (attemptToReleaseStagingTexture)
@@ -275,7 +280,7 @@
     ASSERT(mAssociatedStorage == textureStorage);
 }
 
-gl::Error Image11::recoverFromAssociatedStorage()
+gl::Error Image11::recoverFromAssociatedStorage(const gl::Context *context)
 {
     if (mRecoverFromStorage)
     {
@@ -285,8 +290,8 @@
 
         // CopySubResource from the Storage to the Staging texture
         gl::Box region(0, 0, 0, mWidth, mHeight, mDepth);
-        ANGLE_TRY(mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource,
-                                                           mAssociatedImageIndex, region));
+        ANGLE_TRY(mAssociatedStorage->copySubresourceLevel(
+            context, mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region));
         mRecoveredFromStorageCount += 1;
 
         // Reset all the recovery parameters, even if the texture storage association is broken.
@@ -356,7 +361,8 @@
 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as
 // format/type at input
 // into the target pixel rectangle.
-gl::Error Image11::loadData(const gl::Box &area,
+gl::Error Image11::loadData(const gl::Context *context,
+                            const gl::Box &area,
                             const gl::PixelUnpackState &unpack,
                             GLenum type,
                             const void *input,
@@ -383,7 +389,7 @@
     LoadImageFunction loadFunction = d3dFormatInfo.getLoadFunctions()(type).loadFunction;
 
     D3D11_MAPPED_SUBRESOURCE mappedImage;
-    ANGLE_TRY(map(D3D11_MAP_WRITE, &mappedImage));
+    ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage));
 
     uint8_t *offsetMappedData = (reinterpret_cast<uint8_t *>(mappedImage.pData) +
                                  (area.y * mappedImage.RowPitch + area.x * outputPixelSize +
@@ -397,7 +403,9 @@
     return gl::NoError();
 }
 
-gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input)
+gl::Error Image11::loadCompressedData(const gl::Context *context,
+                                      const gl::Box &area,
+                                      const void *input)
 {
     const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
     GLsizei inputRowPitch                = 0;
@@ -419,7 +427,7 @@
         d3dFormatInfo.getLoadFunctions()(GL_UNSIGNED_BYTE).loadFunction;
 
     D3D11_MAPPED_SUBRESOURCE mappedImage;
-    ANGLE_TRY(map(D3D11_MAP_WRITE, &mappedImage));
+    ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage));
 
     uint8_t *offsetMappedData =
         reinterpret_cast<uint8_t *>(mappedImage.pData) +
@@ -435,12 +443,14 @@
     return gl::NoError();
 }
 
-gl::Error Image11::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source)
+gl::Error Image11::copyFromTexStorage(const gl::Context *context,
+                                      const gl::ImageIndex &imageIndex,
+                                      TextureStorage *source)
 {
     TextureStorage11 *storage11 = GetAs<TextureStorage11>(source);
 
     const TextureHelper11 *textureHelper = nullptr;
-    ANGLE_TRY(storage11->getResource(&textureHelper));
+    ANGLE_TRY(storage11->getResource(context, &textureHelper));
 
     UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex);
 
@@ -448,7 +458,8 @@
     return copyWithoutConversion(gl::Offset(), sourceBox, *textureHelper, subresourceIndex);
 }
 
-gl::Error Image11::copyFromFramebuffer(const gl::Offset &destOffset,
+gl::Error Image11::copyFromFramebuffer(const gl::Context *context,
+                                       const gl::Offset &destOffset,
                                        const gl::Rectangle &sourceArea,
                                        const gl::Framebuffer *sourceFBO)
 {
@@ -462,7 +473,7 @@
     if (d3d11Format.texFormat == mDXGIFormat && sourceInternalFormat == mInternalFormat)
     {
         RenderTarget11 *rt11 = nullptr;
-        ANGLE_TRY(srcAttachment->getRenderTarget(&rt11));
+        ANGLE_TRY(srcAttachment->getRenderTarget(context, &rt11));
         ASSERT(rt11->getTexture().get());
 
         TextureHelper11 textureHelper  = rt11->getTexture();
@@ -475,7 +486,7 @@
     // This format requires conversion, so we must copy the texture to staging and manually convert
     // via readPixels
     D3D11_MAPPED_SUBRESOURCE mappedImage;
-    ANGLE_TRY(map(D3D11_MAP_WRITE, &mappedImage));
+    ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage));
 
     // determine the offset coordinate into the destination buffer
     const auto &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
@@ -498,9 +509,9 @@
         mRenderer->getScratchMemoryBuffer(bufferSize, &memoryBuffer);
         GLuint memoryBufferRowPitch = destFormatInfo.pixelBytes * sourceArea.width;
 
-        error = mRenderer->readFromAttachment(*srcAttachment, sourceArea, destFormatInfo.format,
-                                              destFormatInfo.type, memoryBufferRowPitch,
-                                              gl::PixelPackState(), memoryBuffer->data());
+        error = mRenderer->readFromAttachment(
+            context, *srcAttachment, sourceArea, destFormatInfo.format, destFormatInfo.type,
+            memoryBufferRowPitch, gl::PixelPackState(), memoryBuffer->data());
 
         loadFunction.loadFunction(sourceArea.width, sourceArea.height, 1, memoryBuffer->data(),
                                   memoryBufferRowPitch, 0, dataOffset, mappedImage.RowPitch,
@@ -508,9 +519,9 @@
     }
     else
     {
-        error = mRenderer->readFromAttachment(*srcAttachment, sourceArea, destFormatInfo.format,
-                                              destFormatInfo.type, mappedImage.RowPitch,
-                                              gl::PixelPackState(), dataOffset);
+        error = mRenderer->readFromAttachment(
+            context, *srcAttachment, sourceArea, destFormatInfo.format, destFormatInfo.type,
+            mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
     }
 
     unmap();
@@ -686,10 +697,10 @@
     return gl::NoError();
 }
 
-gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
+gl::Error Image11::map(const gl::Context *context, D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
 {
     // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE.
-    ANGLE_TRY(recoverFromAssociatedStorage());
+    ANGLE_TRY(recoverFromAssociatedStorage(context));
 
     const TextureHelper11 *stagingTexture = nullptr;
     unsigned int subresourceIndex  = 0;
diff --git a/src/libANGLE/renderer/d3d/d3d11/Image11.h b/src/libANGLE/renderer/d3d/d3d11/Image11.h
index 6bf99e0..1adcf68 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Image11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Image11.h
@@ -33,10 +33,12 @@
     Image11(Renderer11 *renderer);
     virtual ~Image11();
 
-    static gl::Error generateMipmap(Image11 *dest,
+    static gl::Error GenerateMipmap(const gl::Context *context,
+                                    Image11 *dest,
                                     Image11 *src,
                                     const Renderer11DeviceCaps &rendererCaps);
-    static gl::Error copyImage(Image11 *dest,
+    static gl::Error CopyImage(const gl::Context *context,
+                               Image11 *dest,
                                Image11 *source,
                                const gl::Rectangle &sourceRect,
                                const gl::Offset &destOffset,
@@ -47,30 +49,39 @@
 
     virtual bool isDirty() const;
 
-    virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+    gl::Error copyToStorage(const gl::Context *context,
+                            TextureStorage *storage,
+                            const gl::ImageIndex &index,
+                            const gl::Box &region) override;
 
     bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override;
 
     DXGI_FORMAT getDXGIFormat() const;
 
-    gl::Error loadData(const gl::Box &area,
+    gl::Error loadData(const gl::Context *context,
+                       const gl::Box &area,
                        const gl::PixelUnpackState &unpack,
                        GLenum type,
                        const void *input,
                        bool applySkipImages) override;
-    gl::Error loadCompressedData(const gl::Box &area, const void *input) override;
+    gl::Error loadCompressedData(const gl::Context *context,
+                                 const gl::Box &area,
+                                 const void *input) override;
 
-    gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override;
-    gl::Error copyFromFramebuffer(const gl::Offset &destOffset,
+    gl::Error copyFromTexStorage(const gl::Context *context,
+                                 const gl::ImageIndex &imageIndex,
+                                 TextureStorage *source) override;
+    gl::Error copyFromFramebuffer(const gl::Context *context,
+                                  const gl::Offset &destOffset,
                                   const gl::Rectangle &sourceArea,
                                   const gl::Framebuffer *source) override;
 
-    gl::Error recoverFromAssociatedStorage();
+    gl::Error recoverFromAssociatedStorage(const gl::Context *context);
     void verifyAssociatedStorageValid(TextureStorage11 *textureStorage) const;
     void disassociateStorage();
 
   protected:
-    gl::Error map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
+    gl::Error map(const gl::Context *context, D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
     void unmap();
 
   private:
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
index 629c3a3..570eab4 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -1362,7 +1362,7 @@
         ASSERT(textureD3D);
 
         TextureStorage *texStorage = nullptr;
-        ANGLE_TRY(textureD3D->getNativeTexture(&texStorage));
+        ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage));
 
         if (texStorage)
         {
@@ -1406,7 +1406,8 @@
     ANGLE_TRY(generateSwizzles(context, gl::SAMPLER_PIXEL));
     return gl::NoError();
 }
-gl::Error Renderer11::setSamplerState(gl::SamplerType type,
+gl::Error Renderer11::setSamplerState(const gl::Context *context,
+                                      gl::SamplerType type,
                                       int index,
                                       gl::Texture *texture,
                                       const gl::SamplerState &samplerState)
@@ -1416,7 +1417,7 @@
     TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
 
     TextureStorage *storage = nullptr;
-    ANGLE_TRY(textureD3D->getNativeTexture(&storage));
+    ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
 
     // Storage should exist, texture should be complete
     ASSERT(storage);
@@ -1496,7 +1497,10 @@
     return gl::NoError();
 }
 
-gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
+gl::Error Renderer11::setTexture(const gl::Context *context,
+                                 gl::SamplerType type,
+                                 int index,
+                                 gl::Texture *texture)
 {
     const d3d11::SharedSRV *textureSRV = nullptr;
 
@@ -1505,14 +1509,14 @@
         TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
 
         TextureStorage *texStorage = nullptr;
-        ANGLE_TRY(textureImpl->getNativeTexture(&texStorage));
+        ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
 
         // Texture should be complete and have a storage
         ASSERT(texStorage);
 
         TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
 
-        ANGLE_TRY(storage11->getSRV(texture->getTextureState(), &textureSRV));
+        ANGLE_TRY(storage11->getSRV(context, texture->getTextureState(), &textureSRV));
 
         // If we get an invalid SRV here, something went wrong in the texture class and we're
         // unexpectedly missing the shader resource view.
@@ -1545,7 +1549,7 @@
             continue;
         }
 
-        const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
+        const gl::OffsetBindingPointer<gl::Buffer> &uniformBuffer =
             data.getState().getIndexedUniformBuffer(binding);
         GLintptr uniformBufferOffset = uniformBuffer.getOffset();
         GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
@@ -1605,7 +1609,7 @@
             continue;
         }
 
-        const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
+        const gl::OffsetBindingPointer<gl::Buffer> &uniformBuffer =
             data.getState().getIndexedUniformBuffer(binding);
         GLintptr uniformBufferOffset = uniformBuffer.getOffset();
         GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
@@ -1717,17 +1721,18 @@
     return count >= minCount;
 }
 
-gl::Error Renderer11::applyVertexBuffer(const gl::State &state,
+gl::Error Renderer11::applyVertexBuffer(const gl::Context *context,
                                         GLenum mode,
                                         GLint first,
                                         GLsizei count,
                                         GLsizei instances,
                                         TranslatedIndexData *indexInfo)
 {
+    const auto &state       = context->getGLState();
     const auto &vertexArray = state.getVertexArray();
     auto *vertexArray11     = GetImplAs<VertexArray11>(vertexArray);
 
-    ANGLE_TRY(vertexArray11->updateDirtyAndDynamicAttribs(mVertexDataManager, state, first, count,
+    ANGLE_TRY(vertexArray11->updateDirtyAndDynamicAttribs(context, mVertexDataManager, first, count,
                                                           instances));
 
     ANGLE_TRY(mStateManager.updateCurrentValueAttribs(state, mVertexDataManager));
@@ -2026,14 +2031,15 @@
     return gl::NoError();
 }
 
-bool Renderer11::supportsFastIndirectDraw(const gl::State &state, GLenum mode, GLenum type)
+bool Renderer11::supportsFastIndirectDraw(const gl::Context *context, GLenum mode, GLenum type)
 {
-    const auto &vertexArray = state.getVertexArray();
+    const auto &glState     = context->getGLState();
+    const auto &vertexArray = glState.getVertexArray();
     auto *vertexArray11     = GetImplAs<VertexArray11>(vertexArray);
     // Indirect drawing doesn't support dynamic attribute storage since it needs the first and count
     // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported
     // either since we need to simulate them in D3D.
-    if (vertexArray11->hasDynamicAttrib(state) || mode == GL_LINE_LOOP || mode == GL_TRIANGLE_FAN)
+    if (vertexArray11->hasDynamicAttrib(context) || mode == GL_LINE_LOOP || mode == GL_TRIANGLE_FAN)
     {
         return false;
     }
@@ -2047,31 +2053,32 @@
         // primitive restart index in it since it also needs to know the index range and count.
         // So, for all other situations, we fall back to normal draw instead of indirect draw.
         bool primitiveRestartWorkaround = mIndexDataManager->usePrimitiveRestartWorkaround(
-            state.isPrimitiveRestartEnabled(), type);
+            glState.isPrimitiveRestartEnabled(), type);
         return !mIndexDataManager->isStreamingIndexData(primitiveRestartWorkaround, type,
                                                         elementArrayBuffer);
     }
     return true;
 }
 
-gl::Error Renderer11::drawArraysIndirectImpl(const gl::ContextState &data,
+gl::Error Renderer11::drawArraysIndirectImpl(const gl::Context *context,
                                              GLenum mode,
                                              const void *indirect)
 {
-    if (skipDraw(data, mode))
+    const auto &contextState = context->getContextState();
+    if (skipDraw(contextState, mode))
     {
         return gl::NoError();
     }
 
-    const auto &glState            = data.getState();
+    const auto &glState            = context->getGLState();
     gl::Buffer *drawIndirectBuffer = glState.getDrawIndirectBuffer();
     ASSERT(drawIndirectBuffer);
     Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
     uintptr_t offset  = reinterpret_cast<uintptr_t>(indirect);
 
-    if (supportsFastIndirectDraw(glState, mode, GL_NONE))
+    if (supportsFastIndirectDraw(context, mode, GL_NONE))
     {
-        applyVertexBuffer(glState, mode, 0, 0, 0, nullptr);
+        applyVertexBuffer(context, mode, 0, 0, 0, nullptr);
         ID3D11Buffer *buffer = nullptr;
         ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_INDIRECT), buffer);
         mDeviceContext->DrawInstancedIndirect(buffer, static_cast<unsigned int>(offset));
@@ -2087,42 +2094,43 @@
     GLuint instances = args->instanceCount;
     GLuint first     = args->first;
 
-    ANGLE_TRY(applyVertexBuffer(glState, mode, first, count, instances, nullptr));
+    ANGLE_TRY(applyVertexBuffer(context, mode, first, count, instances, nullptr));
 
     if (mode == GL_LINE_LOOP)
     {
-        return drawLineLoop(data, count, GL_NONE, nullptr, 0, instances);
+        return drawLineLoop(contextState, count, GL_NONE, nullptr, 0, instances);
     }
     if (mode == GL_TRIANGLE_FAN)
     {
-        return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances);
+        return drawTriangleFan(contextState, count, GL_NONE, nullptr, 0, instances);
     }
 
     mDeviceContext->DrawInstanced(count, instances, 0, 0);
     return gl::NoError();
 }
 
-gl::Error Renderer11::drawElementsIndirectImpl(const gl::ContextState &data,
+gl::Error Renderer11::drawElementsIndirectImpl(const gl::Context *context,
                                                GLenum mode,
                                                GLenum type,
                                                const void *indirect)
 {
-    if (skipDraw(data, mode))
+    const auto &contextState = context->getContextState();
+    if (skipDraw(contextState, mode))
     {
         return gl::NoError();
     }
 
-    const auto &glState            = data.getState();
+    const auto &glState            = context->getGLState();
     gl::Buffer *drawIndirectBuffer = glState.getDrawIndirectBuffer();
     ASSERT(drawIndirectBuffer);
     Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
     uintptr_t offset  = reinterpret_cast<uintptr_t>(indirect);
 
     TranslatedIndexData indexInfo;
-    if (supportsFastIndirectDraw(glState, mode, type))
+    if (supportsFastIndirectDraw(context, mode, type))
     {
-        ANGLE_TRY(applyIndexBuffer(data, nullptr, 0, mode, type, &indexInfo));
-        ANGLE_TRY(applyVertexBuffer(glState, mode, 0, 0, 0, &indexInfo));
+        ANGLE_TRY(applyIndexBuffer(contextState, nullptr, 0, mode, type, &indexInfo));
+        ANGLE_TRY(applyVertexBuffer(context, mode, 0, 0, 0, &indexInfo));
         ID3D11Buffer *buffer = nullptr;
         ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_INDIRECT), buffer);
         mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast<unsigned int>(offset));
@@ -2150,20 +2158,20 @@
                                                 glState.isPrimitiveRestartEnabled(), &indexRange));
 
     indexInfo.indexRange = indexRange;
-    ANGLE_TRY(applyIndexBuffer(data, indices, count, mode, type, &indexInfo));
+    ANGLE_TRY(applyIndexBuffer(contextState, indices, count, mode, type, &indexInfo));
     size_t vertexCount = indexRange.vertexCount();
-    ANGLE_TRY(applyVertexBuffer(glState, mode, static_cast<GLsizei>(indexRange.start) + baseVertex,
+    ANGLE_TRY(applyVertexBuffer(context, mode, static_cast<GLsizei>(indexRange.start) + baseVertex,
                                 static_cast<GLsizei>(vertexCount), instances, &indexInfo));
 
     int baseVertexLocation = -static_cast<int>(indexRange.start);
     if (mode == GL_LINE_LOOP)
     {
-        return drawLineLoop(data, count, type, indices, baseVertexLocation, instances);
+        return drawLineLoop(contextState, count, type, indices, baseVertexLocation, instances);
     }
 
     if (mode == GL_TRIANGLE_FAN)
     {
-        return drawTriangleFan(data, count, type, indices, baseVertexLocation, instances);
+        return drawTriangleFan(contextState, count, type, indices, baseVertexLocation, instances);
     }
 
     mDeviceContext->DrawIndexedInstanced(count, instances, 0, baseVertexLocation, 0);
@@ -3168,7 +3176,7 @@
     ASSERT(colorAttachment);
 
     RenderTarget11 *sourceRenderTarget = nullptr;
-    ANGLE_TRY(colorAttachment->getRenderTarget(&sourceRenderTarget));
+    ANGLE_TRY(colorAttachment->getRenderTarget(context, &sourceRenderTarget));
     ASSERT(sourceRenderTarget);
 
     const d3d11::SharedSRV &source = sourceRenderTarget->getBlitShaderResourceView();
@@ -3214,7 +3222,7 @@
 
     gl::ImageIndex index              = gl::ImageIndex::Make2D(level);
     RenderTargetD3D *destRenderTarget = nullptr;
-    ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
+    ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
     ASSERT(destRenderTarget);
 
     ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
@@ -3239,7 +3247,7 @@
 
     gl::ImageIndex index              = gl::ImageIndex::MakeCube(target, level);
     RenderTargetD3D *destRenderTarget = nullptr;
-    ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
+    ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
     ASSERT(destRenderTarget);
 
     ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
@@ -3263,7 +3271,7 @@
 
     gl::ImageIndex index              = gl::ImageIndex::Make3D(level, destOffset.z);
     RenderTargetD3D *destRenderTarget = nullptr;
-    ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
+    ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
     ASSERT(destRenderTarget);
 
     ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
@@ -3287,7 +3295,7 @@
 
     gl::ImageIndex index              = gl::ImageIndex::Make2DArray(level, destOffset.z);
     RenderTargetD3D *destRenderTarget = nullptr;
-    ANGLE_TRY(storage11->getRenderTarget(index, &destRenderTarget));
+    ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
     ASSERT(destRenderTarget);
 
     ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
@@ -3310,10 +3318,10 @@
                                   bool unpackPremultiplyAlpha,
                                   bool unpackUnmultiplyAlpha)
 {
-    const TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+    TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
 
     TextureStorage *sourceStorage = nullptr;
-    ANGLE_TRY(const_cast<TextureD3D *>(sourceD3D)->getNativeTexture(&sourceStorage));
+    ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
 
     TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
     ASSERT(sourceStorage11);
@@ -3327,13 +3335,13 @@
         sourceStorage11->getFormatSet().texFormat == destStorage11->getFormatSet().texFormat)
     {
         const TextureHelper11 *sourceResource = nullptr;
-        ANGLE_TRY(sourceStorage11->getResource(&sourceResource));
+        ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource));
 
         gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
         UINT sourceSubresource     = sourceStorage11->getSubresourceIndex(sourceIndex);
 
         const TextureHelper11 *destResource = nullptr;
-        ANGLE_TRY(destStorage11->getResource(&destResource));
+        ANGLE_TRY(destStorage11->getResource(context, &destResource));
 
         gl::ImageIndex destIndex = gl::ImageIndex::MakeGeneric(destTarget, destLevel);
         UINT destSubresource     = destStorage11->getSubresourceIndex(destIndex);
@@ -3354,11 +3362,11 @@
     else
     {
         const d3d11::SharedSRV *sourceSRV = nullptr;
-        ANGLE_TRY(sourceStorage11->getSRVLevels(sourceLevel, sourceLevel, &sourceSRV));
+        ANGLE_TRY(sourceStorage11->getSRVLevels(context, sourceLevel, sourceLevel, &sourceSRV));
 
         gl::ImageIndex destIndex             = gl::ImageIndex::MakeGeneric(destTarget, destLevel);
         RenderTargetD3D *destRenderTargetD3D = nullptr;
-        ANGLE_TRY(destStorage11->getRenderTarget(destIndex, &destRenderTargetD3D));
+        ANGLE_TRY(destStorage11->getRenderTarget(context, destIndex, &destRenderTargetD3D));
 
         RenderTarget11 *destRenderTarget11 = GetAs<RenderTarget11>(destRenderTargetD3D);
 
@@ -3391,7 +3399,8 @@
     return gl::NoError();
 }
 
-gl::Error Renderer11::copyCompressedTexture(const gl::Texture *source,
+gl::Error Renderer11::copyCompressedTexture(const gl::Context *context,
+                                            const gl::Texture *source,
                                             GLint sourceLevel,
                                             TextureStorage *storage,
                                             GLint destLevel)
@@ -3400,7 +3409,7 @@
     ASSERT(destStorage11);
 
     const TextureHelper11 *destResource = nullptr;
-    ANGLE_TRY(destStorage11->getResource(&destResource));
+    ANGLE_TRY(destStorage11->getResource(context, &destResource));
 
     gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
     UINT destSubresource     = destStorage11->getSubresourceIndex(destIndex);
@@ -3409,13 +3418,13 @@
     ASSERT(sourceD3D);
 
     TextureStorage *sourceStorage = nullptr;
-    ANGLE_TRY(sourceD3D->getNativeTexture(&sourceStorage));
+    ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
 
     TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
     ASSERT(sourceStorage11);
 
     const TextureHelper11 *sourceResource = nullptr;
-    ANGLE_TRY(sourceStorage11->getResource(&sourceResource));
+    ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource));
 
     gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
     UINT sourceSubresource     = sourceStorage11->getSubresourceIndex(sourceIndex);
@@ -3842,14 +3851,15 @@
     return new Image11(this);
 }
 
-gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src)
+gl::Error Renderer11::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
 {
     Image11 *dest11 = GetAs<Image11>(dest);
     Image11 *src11  = GetAs<Image11>(src);
-    return Image11::generateMipmap(dest11, src11, mRenderer11DeviceCaps);
+    return Image11::GenerateMipmap(context, dest11, src11, mRenderer11DeviceCaps);
 }
 
-gl::Error Renderer11::generateMipmapUsingD3D(TextureStorage *storage,
+gl::Error Renderer11::generateMipmapUsingD3D(const gl::Context *context,
+                                             TextureStorage *storage,
                                              const gl::TextureState &textureState)
 {
     TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
@@ -3858,7 +3868,7 @@
     ASSERT(storage11->supportsNativeMipmapFunction());
 
     const d3d11::SharedSRV *srv = nullptr;
-    ANGLE_TRY(storage11->getSRVLevels(textureState.getEffectiveBaseLevel(),
+    ANGLE_TRY(storage11->getSRVLevels(context, textureState.getEffectiveBaseLevel(),
                                       textureState.getEffectiveMaxLevel(), &srv));
 
     mDeviceContext->GenerateMips(srv->get());
@@ -3866,7 +3876,8 @@
     return gl::NoError();
 }
 
-gl::Error Renderer11::copyImage(ImageD3D *dest,
+gl::Error Renderer11::copyImage(const gl::Context *context,
+                                ImageD3D *dest,
                                 ImageD3D *source,
                                 const gl::Rectangle &sourceRect,
                                 const gl::Offset &destOffset,
@@ -3876,7 +3887,7 @@
 {
     Image11 *dest11 = GetAs<Image11>(dest);
     Image11 *src11  = GetAs<Image11>(source);
-    return Image11::copyImage(dest11, src11, sourceRect, destOffset, unpackFlipY,
+    return Image11::CopyImage(context, dest11, src11, sourceRect, destOffset, unpackFlipY,
                               unpackPremultiplyAlpha, unpackUnmultiplyAlpha, mRenderer11DeviceCaps);
 }
 
@@ -3942,7 +3953,8 @@
                                         levels);
 }
 
-gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAttachment,
+gl::Error Renderer11::readFromAttachment(const gl::Context *context,
+                                         const gl::FramebufferAttachment &srcAttachment,
                                          const gl::Rectangle &sourceArea,
                                          GLenum format,
                                          GLenum type,
@@ -3956,7 +3968,7 @@
     const bool invertTexture = UsePresentPathFast(this, &srcAttachment);
 
     RenderTarget11 *rt11 = nullptr;
-    ANGLE_TRY(srcAttachment.getRenderTarget(&rt11));
+    ANGLE_TRY(srcAttachment.getRenderTarget(context, &rt11));
     ASSERT(rt11->getTexture().valid());
 
     const TextureHelper11 &textureHelper = rt11->getTexture();
@@ -4058,12 +4070,12 @@
     // tracking in the 'pixelBuffer' members, causing leaks. Instead we must use
     // pixelBuffer.set() twice, which performs the addRef/release correctly
     invertTexturePack.alignment = pack.alignment;
-    invertTexturePack.pixelBuffer.set(pack.pixelBuffer.get());
+    invertTexturePack.pixelBuffer.set(context, pack.pixelBuffer.get());
     invertTexturePack.reverseRowOrder = !pack.reverseRowOrder;
 
     PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, 0);
     gl::Error error = packPixels(stagingHelper, packParams, pixelsOut);
-    invertTexturePack.pixelBuffer.set(nullptr);
+    invertTexturePack.pixelBuffer.set(context, nullptr);
     ANGLE_TRY(error);
     return gl::NoError();
 }
@@ -4536,7 +4548,10 @@
     return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps, mAdapterDescription);
 }
 
-gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd)
+gl::Error Renderer11::clearTextures(const gl::Context *context,
+                                    gl::SamplerType samplerType,
+                                    size_t rangeStart,
+                                    size_t rangeEnd)
 {
     return mStateManager.clearTextures(samplerType, rangeStart, rangeEnd);
 }
@@ -4603,7 +4618,7 @@
     ASSERT(!glState.isTransformFeedbackActiveUnpaused());
 
     size_t vertexCount = indexInfo.indexRange.vertexCount();
-    ANGLE_TRY(applyVertexBuffer(glState, mode, static_cast<GLsizei>(indexInfo.indexRange.start),
+    ANGLE_TRY(applyVertexBuffer(context, mode, static_cast<GLsizei>(indexInfo.indexRange.start),
                                 static_cast<GLsizei>(vertexCount), instances, &indexInfo));
     ANGLE_TRY(applyTextures(context));
     ANGLE_TRY(applyShaders(data, mode));
@@ -4640,7 +4655,7 @@
 
     ANGLE_TRY(mStateManager.updateState(context, mode));
     ANGLE_TRY(applyTransformFeedbackBuffers(data));
-    ANGLE_TRY(applyVertexBuffer(glState, mode, first, count, instances, nullptr));
+    ANGLE_TRY(applyVertexBuffer(context, mode, first, count, instances, nullptr));
     ANGLE_TRY(applyTextures(context));
     ANGLE_TRY(applyShaders(data, mode));
     ANGLE_TRY(programD3D->applyUniformBuffers(data));
@@ -4663,8 +4678,8 @@
                                           GLenum type,
                                           const void *indirect)
 {
-    const auto &data     = context->getContextState();
-    const auto &glState  = data.getState();
+    const auto &contextState = context->getContextState();
+    const auto &glState      = context->getGLState();
     gl::Program *program = glState.getProgram();
     ASSERT(program != nullptr);
     ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
@@ -4674,19 +4689,19 @@
     ANGLE_TRY(generateSwizzles(context));
     applyPrimitiveType(mode, 0, usesPointSize);
     ANGLE_TRY(mStateManager.updateState(context, mode));
-    ANGLE_TRY(applyTransformFeedbackBuffers(data));
+    ANGLE_TRY(applyTransformFeedbackBuffers(contextState));
     ASSERT(!glState.isTransformFeedbackActiveUnpaused());
     ANGLE_TRY(applyTextures(context));
-    ANGLE_TRY(applyShaders(data, mode));
-    ANGLE_TRY(programD3D->applyUniformBuffers(data));
+    ANGLE_TRY(applyShaders(contextState, mode));
+    ANGLE_TRY(programD3D->applyUniformBuffers(contextState));
 
     if (type == GL_NONE)
     {
-        ANGLE_TRY(drawArraysIndirectImpl(data, mode, indirect));
+        ANGLE_TRY(drawArraysIndirectImpl(context, mode, indirect));
     }
     else
     {
-        ANGLE_TRY(drawElementsIndirectImpl(data, mode, type, indirect));
+        ANGLE_TRY(drawElementsIndirectImpl(context, mode, type, indirect));
     }
 
     return gl::NoError();
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
index 0fc72d0..06b5a80 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -138,11 +138,15 @@
                                    HANDLE shareHandle,
                                    const egl::AttributeMap &attribs) const override;
 
-    gl::Error setSamplerState(gl::SamplerType type,
+    gl::Error setSamplerState(const gl::Context *context,
+                              gl::SamplerType type,
                               int index,
                               gl::Texture *texture,
                               const gl::SamplerState &sampler) override;
-    gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) override;
+    gl::Error setTexture(const gl::Context *context,
+                         gl::SamplerType type,
+                         int index,
+                         gl::Texture *texture) override;
 
     gl::Error setUniformBuffers(const gl::ContextState &data,
                                 const std::vector<GLint> &vertexUniformBuffers,
@@ -152,7 +156,7 @@
     gl::Error applyUniforms(const ProgramD3D &programD3D,
                             GLenum drawMode,
                             const std::vector<D3DUniform *> &uniformArray) override;
-    gl::Error applyVertexBuffer(const gl::State &state,
+    gl::Error applyVertexBuffer(const gl::Context *context,
                                 GLenum mode,
                                 GLint first,
                                 GLsizei count,
@@ -229,7 +233,8 @@
                           bool unpackFlipY,
                           bool unpackPremultiplyAlpha,
                           bool unpackUnmultiplyAlpha) override;
-    gl::Error copyCompressedTexture(const gl::Texture *source,
+    gl::Error copyCompressedTexture(const gl::Context *context,
+                                    const gl::Texture *source,
                                     GLint sourceLevel,
                                     TextureStorage *storage,
                                     GLint destLevel) override;
@@ -262,10 +267,12 @@
 
     // Image operations
     ImageD3D *createImage() override;
-    gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
-    gl::Error generateMipmapUsingD3D(TextureStorage *storage,
+    gl::Error generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *source) override;
+    gl::Error generateMipmapUsingD3D(const gl::Context *context,
+                                     TextureStorage *storage,
                                      const gl::TextureState &textureState) override;
-    gl::Error copyImage(ImageD3D *dest,
+    gl::Error copyImage(const gl::Context *context,
+                        ImageD3D *dest,
                         ImageD3D *source,
                         const gl::Rectangle &sourceRect,
                         const gl::Offset &destOffset,
@@ -357,7 +364,8 @@
                                                            GLsizei count,
                                                            GLsizei instances) const override;
 
-    gl::Error readFromAttachment(const gl::FramebufferAttachment &srcAttachment,
+    gl::Error readFromAttachment(const gl::Context *context,
+                                 const gl::FramebufferAttachment &srcAttachment,
                                  const gl::Rectangle &sourceArea,
                                  GLenum format,
                                  GLenum type,
@@ -465,7 +473,8 @@
                               TextureHelper11 *textureOut);
 
   protected:
-    gl::Error clearTextures(gl::SamplerType samplerType,
+    gl::Error clearTextures(const gl::Context *context,
+                            gl::SamplerType samplerType,
                             size_t rangeStart,
                             size_t rangeEnd) override;
 
@@ -482,16 +491,14 @@
                                GLenum type,
                                const void *indices,
                                GLsizei instances);
-    gl::Error drawArraysIndirectImpl(const gl::ContextState &data,
-                                     GLenum mode,
-                                     const void *indirect);
-    gl::Error drawElementsIndirectImpl(const gl::ContextState &data,
+    gl::Error drawArraysIndirectImpl(const gl::Context *context, GLenum mode, const void *indirect);
+    gl::Error drawElementsIndirectImpl(const gl::Context *context,
                                        GLenum mode,
                                        GLenum type,
                                        const void *indirect);
 
     // Support directly using indirect draw buffer.
-    bool supportsFastIndirectDraw(const gl::State &state, GLenum mode, GLenum type);
+    bool supportsFastIndirectDraw(const gl::Context *context, GLenum mode, GLenum type);
 
     void generateCaps(gl::Caps *outCaps,
                       gl::TextureCapsMap *outTextureCaps,
diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
index dee4a3b..f59f081 100644
--- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -870,9 +870,9 @@
     mCurrentQueries.erase(query);
 }
 
-gl::Error StateManager11::onMakeCurrent(const gl::ContextState &data)
+gl::Error StateManager11::onMakeCurrent(const gl::Context *context)
 {
-    const gl::State &state = data.getState();
+    const gl::State &state = context->getGLState();
 
     for (Query11 *query : mCurrentQueries)
     {
@@ -1011,7 +1011,7 @@
 gl::Error StateManager11::syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer)
 {
     Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
-    ANGLE_TRY(framebuffer11->markAttachmentsDirty());
+    ANGLE_TRY(framebuffer11->markAttachmentsDirty(context));
 
     if (framebuffer11->hasAnyInternalDirtyBit())
     {
@@ -1268,7 +1268,7 @@
     {
         ASSERT(firstColorAttachment->isAttached());
         RenderTarget11 *renderTarget = nullptr;
-        ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
+        ANGLE_TRY(firstColorAttachment->getRenderTarget(context, &renderTarget));
         samples = renderTarget->getSamples();
     }
     gl::RasterizerState rasterizer = glState.getRasterizerState();
diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
index 4ccd6c6..e5fb43d 100644
--- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
@@ -82,7 +82,7 @@
 
     void onBeginQuery(Query11 *query);
     void onDeleteQueryObject(Query11 *query);
-    gl::Error onMakeCurrent(const gl::ContextState &data);
+    gl::Error onMakeCurrent(const gl::Context *context);
 
     gl::Error updateCurrentValueAttribs(const gl::State &state,
                                         VertexDataManager *vertexDataManager);
diff --git a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
index b6cd8a3..4303e9a 100644
--- a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -167,7 +167,8 @@
     return subresource;
 }
 
-gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState,
+gl::Error TextureStorage11::getSRV(const gl::Context *context,
+                                   const gl::TextureState &textureState,
                                    const d3d11::SharedSRV **outSRV)
 {
     // Make sure to add the level offset for our tiny compressed texture workaround
@@ -214,7 +215,7 @@
     {
         // Ensure drop texture gets created.
         DropStencil result = DropStencil::CREATED;
-        ANGLE_TRY_RESULT(ensureDropStencilTexture(), result);
+        ANGLE_TRY_RESULT(ensureDropStencilTexture(context), result);
 
         // Clear the SRV cache if necessary.
         // TODO(jmadill): Re-use find query result.
@@ -225,12 +226,14 @@
         }
     }
 
-    ANGLE_TRY(getCachedOrCreateSRV(key, outSRV));
+    ANGLE_TRY(getCachedOrCreateSRV(context, key, outSRV));
 
     return gl::NoError();
 }
 
-gl::Error TextureStorage11::getCachedOrCreateSRV(const SRVKey &key, const d3d11::SharedSRV **outSRV)
+gl::Error TextureStorage11::getCachedOrCreateSRV(const gl::Context *context,
+                                                 const SRVKey &key,
+                                                 const d3d11::SharedSRV **outSRV)
 {
     auto iter = mSrvCache.find(key);
     if (iter != mSrvCache.end())
@@ -258,13 +261,13 @@
     }
     else
     {
-        ANGLE_TRY(getResource(&texture));
+        ANGLE_TRY(getResource(context, &texture));
         format = mFormatInfo.srvFormat;
     }
 
     d3d11::SharedSRV srv;
 
-    ANGLE_TRY(createSRV(key.baseLevel, key.mipLevels, format, *texture, &srv));
+    ANGLE_TRY(createSRV(context, key.baseLevel, key.mipLevels, format, *texture, &srv));
 
     const auto &insertIt = mSrvCache.insert(std::make_pair(key, std::move(srv)));
     *outSRV              = &insertIt.first->second;
@@ -272,7 +275,10 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11::getSRVLevel(int mipLevel, bool blitSRV, const d3d11::SharedSRV **outSRV)
+gl::Error TextureStorage11::getSRVLevel(const gl::Context *context,
+                                        int mipLevel,
+                                        bool blitSRV,
+                                        const d3d11::SharedSRV **outSRV)
 {
     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
 
@@ -289,11 +295,12 @@
         else
         {
             const TextureHelper11 *resource = nullptr;
-            ANGLE_TRY(getResource(&resource));
+            ANGLE_TRY(getResource(context, &resource));
 
             DXGI_FORMAT resourceFormat =
                 blitSRV ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat;
-            ANGLE_TRY(createSRV(mipLevel, 1, resourceFormat, *resource, &levelSRVs[mipLevel]));
+            ANGLE_TRY(
+                createSRV(context, mipLevel, 1, resourceFormat, *resource, &levelSRVs[mipLevel]));
         }
     }
 
@@ -302,7 +309,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11::getSRVLevels(GLint baseLevel,
+gl::Error TextureStorage11::getSRVLevels(const gl::Context *context,
+                                         GLint baseLevel,
                                          GLint maxLevel,
                                          const d3d11::SharedSRV **outSRV)
 {
@@ -326,7 +334,7 @@
     // TODO(jmadill): Assert we don't need to drop stencil.
 
     SRVKey key(baseLevel, mipLevels, false, false);
-    ANGLE_TRY(getCachedOrCreateSRV(key, outSRV));
+    ANGLE_TRY(getCachedOrCreateSRV(context, key, outSRV));
 
     return gl::NoError();
 }
@@ -346,7 +354,7 @@
         {
             // Need to re-render the swizzle for this level
             const d3d11::SharedSRV *sourceSRV = nullptr;
-            ANGLE_TRY(getSRVLevel(level, true, &sourceSRV));
+            ANGLE_TRY(getSRVLevel(context, level, true, &sourceSRV));
 
             const d3d11::RenderTargetView *destRTV;
             ANGLE_TRY(getSwizzleRenderTarget(level, &destRTV));
@@ -384,7 +392,8 @@
     }
 }
 
-gl::Error TextureStorage11::updateSubresourceLevel(const TextureHelper11 &srcTexture,
+gl::Error TextureStorage11::updateSubresourceLevel(const gl::Context *context,
+                                                   const TextureHelper11 &srcTexture,
                                                    unsigned int sourceSubresource,
                                                    const gl::ImageIndex &index,
                                                    const gl::Box &copyArea)
@@ -407,11 +416,11 @@
     // should update the mipmapped texture, even if mapmaps are currently disabled.
     if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
     {
-        ANGLE_TRY(getMippedResource(&dstTexture));
+        ANGLE_TRY(getMippedResource(context, &dstTexture));
     }
     else
     {
-        ANGLE_TRY(getResource(&dstTexture));
+        ANGLE_TRY(getResource(context, &dstTexture));
     }
 
     unsigned int dstSubresource = getSubresourceIndex(index);
@@ -438,15 +447,16 @@
     srcBox.front = copyArea.z;
     srcBox.back  = copyArea.z + copyArea.depth;
 
-    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
 
-    context->CopySubresourceRegion(dstTexture->get(), dstSubresource, copyArea.x, copyArea.y,
-                                   copyArea.z, srcTexture.get(), sourceSubresource,
-                                   fullCopy ? nullptr : &srcBox);
+    deviceContext->CopySubresourceRegion(dstTexture->get(), dstSubresource, copyArea.x, copyArea.y,
+                                         copyArea.z, srcTexture.get(), sourceSubresource,
+                                         fullCopy ? nullptr : &srcBox);
     return gl::NoError();
 }
 
-gl::Error TextureStorage11::copySubresourceLevel(const TextureHelper11 &dstTexture,
+gl::Error TextureStorage11::copySubresourceLevel(const gl::Context *context,
+                                                 const TextureHelper11 &dstTexture,
                                                  unsigned int dstSubresource,
                                                  const gl::ImageIndex &index,
                                                  const gl::Box &region)
@@ -459,18 +469,18 @@
     // should update the mipmapped texture, even if mapmaps are currently disabled.
     if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
     {
-        ANGLE_TRY(getMippedResource(&srcTexture));
+        ANGLE_TRY(getMippedResource(context, &srcTexture));
     }
     else
     {
-        ANGLE_TRY(getResource(&srcTexture));
+        ANGLE_TRY(getResource(context, &srcTexture));
     }
 
     ASSERT(srcTexture->valid());
 
     unsigned int srcSubresource = getSubresourceIndex(index);
 
-    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
 
     // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox
     // should be nullptr.
@@ -491,8 +501,8 @@
         pSrcBox       = &srcBox;
     }
 
-    context->CopySubresourceRegion(dstTexture.get(), dstSubresource, region.x, region.y, region.z,
-                                   srcTexture->get(), srcSubresource, pSrcBox);
+    deviceContext->CopySubresourceRegion(dstTexture.get(), dstSubresource, region.x, region.y,
+                                         region.z, srcTexture->get(), srcSubresource, pSrcBox);
 
     return gl::NoError();
 }
@@ -506,10 +516,10 @@
     markLevelDirty(destIndex.mipIndex);
 
     RenderTargetD3D *source = nullptr;
-    ANGLE_TRY(getRenderTarget(sourceIndex, &source));
+    ANGLE_TRY(getRenderTarget(context, sourceIndex, &source));
 
     RenderTargetD3D *dest = nullptr;
-    ANGLE_TRY(getRenderTarget(destIndex, &dest));
+    ANGLE_TRY(getRenderTarget(context, destIndex, &dest));
 
     auto rt11                              = GetAs<RenderTarget11>(source);
     const d3d11::SharedSRV &sourceSRV      = rt11->getBlitShaderResourceView();
@@ -548,16 +558,16 @@
     }
 }
 
-gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage11::copyToStorage(const gl::Context *context, TextureStorage *destStorage)
 {
     ASSERT(destStorage);
 
     const TextureHelper11 *sourceResouce = nullptr;
-    ANGLE_TRY(getResource(&sourceResouce));
+    ANGLE_TRY(getResource(context, &sourceResouce));
 
     TextureStorage11 *dest11     = GetAs<TextureStorage11>(destStorage);
     const TextureHelper11 *destResource = nullptr;
-    ANGLE_TRY(dest11->getResource(&destResource));
+    ANGLE_TRY(dest11->getResource(context, &destResource));
 
     ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
     immediateContext->CopyResource(destResource->get(), sourceResouce->get());
@@ -567,7 +577,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11::setData(const gl::ImageIndex &index,
+gl::Error TextureStorage11::setData(const gl::Context *context,
+                                    const gl::ImageIndex &index,
                                     ImageD3D *image,
                                     const gl::Box *destBox,
                                     GLenum type,
@@ -579,7 +590,7 @@
     markLevelDirty(index.mipIndex);
 
     const TextureHelper11 *resource = nullptr;
-    ANGLE_TRY(getResource(&resource));
+    ANGLE_TRY(getResource(context, &resource));
     ASSERT(resource && resource->valid());
 
     UINT destSubresource = getSubresourceIndex(index);
@@ -669,7 +680,8 @@
     return gl::NoError();
 }
 
-gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11::ensureDropStencilTexture()
+gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11::ensureDropStencilTexture(
+    const gl::Context *context)
 {
     UNIMPLEMENTED();
     return gl::InternalError() << "Drop stencil texture not implemented.";
@@ -739,7 +751,7 @@
     ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround);
 }
 
-TextureStorage11_2D::~TextureStorage11_2D()
+gl::Error TextureStorage11_2D::onDestroy(const gl::Context *context)
 {
     for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
     {
@@ -749,12 +761,7 @@
 
             // We must let the Images recover their data before we delete it from the
             // TextureStorage.
-            gl::Error error = mAssociatedImages[i]->recoverFromAssociatedStorage();
-            if (error.isError())
-            {
-                // TODO: Find a way to report this back to the context
-                ERR() << "Error initialization texture storage: " << error;
-            }
+            ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
         }
     }
 
@@ -771,9 +778,18 @@
         // desynchronized.
         mRenderer->getStateManager()->invalidateBoundViews();
     }
+
+    delete this;
+
+    return gl::NoError();
 }
 
-gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage)
+TextureStorage11_2D::~TextureStorage11_2D()
+{
+}
+
+gl::Error TextureStorage11_2D::copyToStorage(const gl::Context *context,
+                                             TextureStorage *destStorage)
 {
     ASSERT(destStorage);
 
@@ -789,7 +805,7 @@
             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(false));
 
             const TextureHelper11 *destResource = nullptr;
-            ANGLE_TRY(dest11->getResource(&destResource));
+            ANGLE_TRY(dest11->getResource(context, &destResource));
 
             immediateContext->CopyResource(destResource->get(), mTexture.get());
         }
@@ -799,7 +815,7 @@
             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(true));
 
             const TextureHelper11 *destResource = nullptr;
-            ANGLE_TRY(dest11->getResource(&destResource));
+            ANGLE_TRY(dest11->getResource(context, &destResource));
 
             immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
         }
@@ -808,10 +824,10 @@
     }
 
     const TextureHelper11 *sourceResouce = nullptr;
-    ANGLE_TRY(getResource(&sourceResouce));
+    ANGLE_TRY(getResource(context, &sourceResouce));
 
     const TextureHelper11 *destResource = nullptr;
-    ANGLE_TRY(dest11->getResource(&destResource));
+    ANGLE_TRY(dest11->getResource(context, &destResource));
 
     immediateContext->CopyResource(destResource->get(), sourceResouce->get());
     dest11->markDirty();
@@ -908,7 +924,8 @@
 
 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
 // recover its data before ending the association.
-gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &index,
+gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::Context *context,
+                                                      const gl::ImageIndex &index,
                                                       Image11 *incomingImage)
 {
     const GLint level = index.mipIndex;
@@ -925,14 +942,15 @@
 
             // Force the image to recover from storage before its data is overwritten.
             // This will reset mAssociatedImages[level] to nullptr too.
-            ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage());
+            ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
         }
     }
 
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_2D::getResource(const TextureHelper11 **outResource)
+gl::Error TextureStorage11_2D::getResource(const gl::Context *context,
+                                           const TextureHelper11 **outResource)
 {
     if (mUseLevelZeroTexture && mMipLevels > 1)
     {
@@ -948,7 +966,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_2D::getMippedResource(const TextureHelper11 **outResource)
+gl::Error TextureStorage11_2D::getMippedResource(const gl::Context *context,
+                                                 const TextureHelper11 **outResource)
 {
     // This shouldn't be called unless the zero max LOD workaround is active.
     ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
@@ -993,7 +1012,9 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureStorage11_2D::getRenderTarget(const gl::Context *context,
+                                               const gl::ImageIndex &index,
+                                               RenderTargetD3D **outRT)
 {
     ASSERT(!index.hasLayer());
 
@@ -1017,13 +1038,13 @@
     }
 
     const TextureHelper11 *texture = nullptr;
-    ANGLE_TRY(getResource(&texture));
+    ANGLE_TRY(getResource(context, &texture));
 
     const d3d11::SharedSRV *srv = nullptr;
-    ANGLE_TRY(getSRVLevel(level, false, &srv));
+    ANGLE_TRY(getSRVLevel(context, level, false, &srv));
 
     const d3d11::SharedSRV *blitSRV = nullptr;
-    ANGLE_TRY(getSRVLevel(level, true, &blitSRV));
+    ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV));
 
     if (mUseLevelZeroTexture)
     {
@@ -1084,7 +1105,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_2D::createSRV(int baseLevel,
+gl::Error TextureStorage11_2D::createSRV(const gl::Context *context,
+                                         int baseLevel,
                                          int mipLevels,
                                          DXGI_FORMAT format,
                                          const TextureHelper11 &texture,
@@ -1181,7 +1203,8 @@
     return gl::NoError();
 }
 
-gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_2D::ensureDropStencilTexture()
+gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_2D::ensureDropStencilTexture(
+    const gl::Context *context)
 {
     if (mDropStencilTexture.valid())
     {
@@ -1206,7 +1229,7 @@
     ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture));
     mDropStencilTexture.setDebugName("TexStorage2D.DropStencil");
 
-    ANGLE_TRY(initDropStencilTexture(gl::ImageIndexIterator::Make2D(0, mMipLevels)));
+    ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::Make2D(0, mMipLevels)));
 
     return DropStencil::CREATED;
 }
@@ -1232,7 +1255,7 @@
     mHasKeyedMutex = (desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
 }
 
-TextureStorage11_External::~TextureStorage11_External()
+gl::Error TextureStorage11_External::onDestroy(const gl::Context *context)
 {
     if (mHasKeyedMutex)
     {
@@ -1240,9 +1263,18 @@
         // desynchronized.
         mRenderer->getStateManager()->invalidateBoundViews();
     }
+
+    delete this;
+
+    return gl::NoError();
 }
 
-gl::Error TextureStorage11_External::copyToStorage(TextureStorage *destStorage)
+TextureStorage11_External::~TextureStorage11_External()
+{
+}
+
+gl::Error TextureStorage11_External::copyToStorage(const gl::Context *context,
+                                                   TextureStorage *destStorage)
 {
     UNIMPLEMENTED();
     return gl::NoError();
@@ -1268,7 +1300,8 @@
     mAssociatedImage = nullptr;
 }
 
-gl::Error TextureStorage11_External::releaseAssociatedImage(const gl::ImageIndex &index,
+gl::Error TextureStorage11_External::releaseAssociatedImage(const gl::Context *context,
+                                                            const gl::ImageIndex &index,
                                                             Image11 *incomingImage)
 {
     ASSERT(index.mipIndex == 0);
@@ -1277,25 +1310,28 @@
     {
         mAssociatedImage->verifyAssociatedStorageValid(this);
 
-        ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage());
+        ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
     }
 
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_External::getResource(const TextureHelper11 **outResource)
+gl::Error TextureStorage11_External::getResource(const gl::Context *context,
+                                                 const TextureHelper11 **outResource)
 {
     *outResource = &mTexture;
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_External::getMippedResource(const TextureHelper11 **outResource)
+gl::Error TextureStorage11_External::getMippedResource(const gl::Context *context,
+                                                       const TextureHelper11 **outResource)
 {
     *outResource = &mTexture;
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_External::getRenderTarget(const gl::ImageIndex &index,
+gl::Error TextureStorage11_External::getRenderTarget(const gl::Context *context,
+                                                     const gl::ImageIndex &index,
                                                      RenderTargetD3D **outRT)
 {
     // Render targets are not supported for external textures
@@ -1303,7 +1339,8 @@
     return gl::InternalError();
 }
 
-gl::Error TextureStorage11_External::createSRV(int baseLevel,
+gl::Error TextureStorage11_External::createSRV(const gl::Context *context,
+                                               int baseLevel,
                                                int mipLevels,
                                                DXGI_FORMAT format,
                                                const TextureHelper11 &texture,
@@ -1366,24 +1403,27 @@
 {
 }
 
-gl::Error TextureStorage11_EGLImage::getResource(const TextureHelper11 **outResource)
+gl::Error TextureStorage11_EGLImage::getResource(const gl::Context *context,
+                                                 const TextureHelper11 **outResource)
 {
-    ANGLE_TRY(checkForUpdatedRenderTarget());
+    ANGLE_TRY(checkForUpdatedRenderTarget(context));
 
     RenderTarget11 *renderTarget11 = nullptr;
-    ANGLE_TRY(getImageRenderTarget(&renderTarget11));
+    ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
     *outResource = &renderTarget11->getTexture();
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_EGLImage::getSRV(const gl::TextureState &textureState,
+gl::Error TextureStorage11_EGLImage::getSRV(const gl::Context *context,
+                                            const gl::TextureState &textureState,
                                             const d3d11::SharedSRV **outSRV)
 {
-    ANGLE_TRY(checkForUpdatedRenderTarget());
-    return TextureStorage11::getSRV(textureState, outSRV);
+    ANGLE_TRY(checkForUpdatedRenderTarget(context));
+    return TextureStorage11::getSRV(context, textureState, outSRV);
 }
 
-gl::Error TextureStorage11_EGLImage::getMippedResource(const TextureHelper11 **)
+gl::Error TextureStorage11_EGLImage::getMippedResource(const gl::Context *context,
+                                                       const TextureHelper11 **)
 {
     // This shouldn't be called unless the zero max LOD workaround is active.
     // EGL images are unavailable in this configuration.
@@ -1391,26 +1431,28 @@
     return gl::InternalError();
 }
 
-gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::ImageIndex &index,
+gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::Context *context,
+                                                     const gl::ImageIndex &index,
                                                      RenderTargetD3D **outRT)
 {
     ASSERT(!index.hasLayer());
     ASSERT(index.mipIndex == 0);
 
-    ANGLE_TRY(checkForUpdatedRenderTarget());
+    ANGLE_TRY(checkForUpdatedRenderTarget(context));
 
-    return mImage->getRenderTarget(outRT);
+    return mImage->getRenderTarget(context, outRT);
 }
 
-gl::Error TextureStorage11_EGLImage::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage11_EGLImage::copyToStorage(const gl::Context *context,
+                                                   TextureStorage *destStorage)
 {
     const TextureHelper11 *sourceResouce = nullptr;
-    ANGLE_TRY(getResource(&sourceResouce));
+    ANGLE_TRY(getResource(context, &sourceResouce));
 
     ASSERT(destStorage);
     TextureStorage11_2D *dest11  = GetAs<TextureStorage11_2D>(destStorage);
     const TextureHelper11 *destResource = nullptr;
-    ANGLE_TRY(dest11->getResource(&destResource));
+    ANGLE_TRY(dest11->getResource(context, &destResource));
 
     ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
     immediateContext->CopyResource(destResource->get(), sourceResouce->get());
@@ -1432,7 +1474,9 @@
 {
 }
 
-gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::ImageIndex &, Image11 *)
+gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::Context *context,
+                                                            const gl::ImageIndex &,
+                                                            Image11 *)
 {
     return gl::NoError();
 }
@@ -1497,10 +1541,10 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget()
+gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget(const gl::Context *context)
 {
     RenderTarget11 *renderTarget11 = nullptr;
-    ANGLE_TRY(getImageRenderTarget(&renderTarget11));
+    ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
 
     if (mCurrentRenderTarget != reinterpret_cast<uintptr_t>(renderTarget11))
     {
@@ -1511,7 +1555,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_EGLImage::createSRV(int baseLevel,
+gl::Error TextureStorage11_EGLImage::createSRV(const gl::Context *context,
+                                               int baseLevel,
                                                int mipLevels,
                                                DXGI_FORMAT format,
                                                const TextureHelper11 &texture,
@@ -1537,7 +1582,7 @@
     else
     {
         RenderTarget11 *renderTarget = nullptr;
-        ANGLE_TRY(getImageRenderTarget(&renderTarget));
+        ANGLE_TRY(getImageRenderTarget(context, &renderTarget));
 
         ASSERT(texture == renderTarget->getTexture());
 
@@ -1547,10 +1592,11 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_EGLImage::getImageRenderTarget(RenderTarget11 **outRT) const
+gl::Error TextureStorage11_EGLImage::getImageRenderTarget(const gl::Context *context,
+                                                          RenderTarget11 **outRT) const
 {
     RenderTargetD3D *renderTargetD3D = nullptr;
-    ANGLE_TRY(mImage->getRenderTarget(&renderTargetD3D));
+    ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));
     *outRT = GetAs<RenderTarget11>(renderTargetD3D);
     return gl::NoError();
 }
@@ -1601,7 +1647,7 @@
     ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround);
 }
 
-TextureStorage11_Cube::~TextureStorage11_Cube()
+gl::Error TextureStorage11_Cube::onDestroy(const gl::Context *context)
 {
     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
     {
@@ -1613,7 +1659,7 @@
 
                 // We must let the Images recover their data before we delete it from the
                 // TextureStorage.
-                mAssociatedImages[face][level]->recoverFromAssociatedStorage();
+                ANGLE_TRY(mAssociatedImages[face][level]->recoverFromAssociatedStorage(context));
             }
         }
     }
@@ -1630,6 +1676,14 @@
             SafeDelete(mRenderTarget[face][level]);
         }
     }
+
+    delete this;
+
+    return gl::NoError();
+}
+
+TextureStorage11_Cube::~TextureStorage11_Cube()
+{
 }
 
 UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const
@@ -1652,7 +1706,8 @@
     }
 }
 
-gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage11_Cube::copyToStorage(const gl::Context *context,
+                                               TextureStorage *destStorage)
 {
     ASSERT(destStorage);
 
@@ -1669,7 +1724,7 @@
             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(false));
 
             const TextureHelper11 *destResource = nullptr;
-            ANGLE_TRY(dest11->getResource(&destResource));
+            ANGLE_TRY(dest11->getResource(context, &destResource));
 
             immediateContext->CopyResource(destResource->get(), mTexture.get());
         }
@@ -1679,7 +1734,7 @@
             ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(true));
 
             const TextureHelper11 *destResource = nullptr;
-            ANGLE_TRY(dest11->getResource(&destResource));
+            ANGLE_TRY(dest11->getResource(context, &destResource));
 
             immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
         }
@@ -1687,10 +1742,10 @@
     else
     {
         const TextureHelper11 *sourceResouce = nullptr;
-        ANGLE_TRY(getResource(&sourceResouce));
+        ANGLE_TRY(getResource(context, &sourceResouce));
 
         const TextureHelper11 *destResource = nullptr;
-        ANGLE_TRY(dest11->getResource(&destResource));
+        ANGLE_TRY(dest11->getResource(context, &destResource));
 
         ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
         immediateContext->CopyResource(destResource->get(), sourceResouce->get());
@@ -1791,7 +1846,8 @@
 
 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
 // recover its data before ending the association.
-gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &index,
+gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::Context *context,
+                                                        const gl::ImageIndex &index,
                                                         Image11 *incomingImage)
 {
     const GLint level       = index.mipIndex;
@@ -1813,7 +1869,8 @@
 
                 // Force the image to recover from storage before its data is overwritten.
                 // This will reset mAssociatedImages[level] to nullptr too.
-                ANGLE_TRY(mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage());
+                ANGLE_TRY(
+                    mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(context));
             }
         }
     }
@@ -1821,7 +1878,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_Cube::getResource(const TextureHelper11 **outResource)
+gl::Error TextureStorage11_Cube::getResource(const gl::Context *context,
+                                             const TextureHelper11 **outResource)
 {
     if (mUseLevelZeroTexture && mMipLevels > 1)
     {
@@ -1837,7 +1895,8 @@
     }
 }
 
-gl::Error TextureStorage11_Cube::getMippedResource(const TextureHelper11 **outResource)
+gl::Error TextureStorage11_Cube::getMippedResource(const gl::Context *context,
+                                                   const TextureHelper11 **outResource)
 {
     // This shouldn't be called unless the zero max LOD workaround is active.
     ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
@@ -1907,7 +1966,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index,
+gl::Error TextureStorage11_Cube::getRenderTarget(const gl::Context *context,
+                                                 const gl::ImageIndex &index,
                                                  RenderTargetD3D **outRT)
 {
     const int faceIndex = index.layerIndex;
@@ -1919,7 +1979,7 @@
     if (!mRenderTarget[faceIndex][level])
     {
         const TextureHelper11 *texture = nullptr;
-        ANGLE_TRY(getResource(&texture));
+        ANGLE_TRY(getResource(context, &texture));
 
         if (mUseLevelZeroTexture)
         {
@@ -2006,7 +2066,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_Cube::createSRV(int baseLevel,
+gl::Error TextureStorage11_Cube::createSRV(const gl::Context *context,
+                                           int baseLevel,
                                            int mipLevels,
                                            DXGI_FORMAT format,
                                            const TextureHelper11 &texture,
@@ -2120,10 +2181,11 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11::initDropStencilTexture(const gl::ImageIndexIterator &it)
+gl::Error TextureStorage11::initDropStencilTexture(const gl::Context *context,
+                                                   const gl::ImageIndexIterator &it)
 {
     const TextureHelper11 *sourceTexture = nullptr;
-    ANGLE_TRY(getResource(&sourceTexture));
+    ANGLE_TRY(getResource(context, &sourceTexture));
 
     gl::ImageIndexIterator itCopy = it;
 
@@ -2142,7 +2204,8 @@
     return gl::NoError();
 }
 
-gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_Cube::ensureDropStencilTexture()
+gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_Cube::ensureDropStencilTexture(
+    const gl::Context *context)
 {
     if (mDropStencilTexture.valid())
     {
@@ -2167,7 +2230,7 @@
     ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture));
     mDropStencilTexture.setDebugName("TexStorageCube.DropStencil");
 
-    ANGLE_TRY(initDropStencilTexture(gl::ImageIndexIterator::MakeCube(0, mMipLevels)));
+    ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::MakeCube(0, mMipLevels)));
 
     return DropStencil::CREATED;
 }
@@ -2203,7 +2266,7 @@
     mTextureDepth  = depth;
 }
 
-TextureStorage11_3D::~TextureStorage11_3D()
+gl::Error TextureStorage11_3D::onDestroy(const gl::Context *context)
 {
     for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
     {
@@ -2213,7 +2276,7 @@
 
             // We must let the Images recover their data before we delete it from the
             // TextureStorage.
-            mAssociatedImages[i]->recoverFromAssociatedStorage();
+            ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
         }
     }
 
@@ -2228,6 +2291,14 @@
     {
         SafeDelete(mLevelRenderTargets[i]);
     }
+
+    delete this;
+
+    return gl::NoError();
+}
+
+TextureStorage11_3D::~TextureStorage11_3D()
+{
 }
 
 void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index)
@@ -2265,7 +2336,8 @@
 
 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
 // recover its data before ending the association.
-gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::ImageIndex &index,
+gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::Context *context,
+                                                      const gl::ImageIndex &index,
                                                       Image11 *incomingImage)
 {
     const GLint level = index.mipIndex;
@@ -2282,14 +2354,15 @@
 
             // Force the image to recover from storage before its data is overwritten.
             // This will reset mAssociatedImages[level] to nullptr too.
-            ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage());
+            ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
         }
     }
 
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_3D::getResource(const TextureHelper11 **outResource)
+gl::Error TextureStorage11_3D::getResource(const gl::Context *context,
+                                           const TextureHelper11 **outResource)
 {
     // If the width, height or depth are not positive this should be treated as an incomplete
     // texture. We handle that here by skipping the d3d texture creation.
@@ -2316,7 +2389,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_3D::createSRV(int baseLevel,
+gl::Error TextureStorage11_3D::createSRV(const gl::Context *context,
+                                         int baseLevel,
                                          int mipLevels,
                                          DXGI_FORMAT format,
                                          const TextureHelper11 &texture,
@@ -2336,7 +2410,9 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureStorage11_3D::getRenderTarget(const gl::Context *context,
+                                               const gl::ImageIndex &index,
+                                               RenderTargetD3D **outRT)
 {
     const int mipLevel = index.mipIndex;
     ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
@@ -2348,13 +2424,13 @@
         if (!mLevelRenderTargets[mipLevel])
         {
             const TextureHelper11 *texture = nullptr;
-            ANGLE_TRY(getResource(&texture));
+            ANGLE_TRY(getResource(context, &texture));
 
             const d3d11::SharedSRV *srv = nullptr;
-            ANGLE_TRY(getSRVLevel(mipLevel, false, &srv));
+            ANGLE_TRY(getSRVLevel(context, mipLevel, false, &srv));
 
             const d3d11::SharedSRV *blitSRV = nullptr;
-            ANGLE_TRY(getSRVLevel(mipLevel, true, &blitSRV));
+            ANGLE_TRY(getSRVLevel(context, mipLevel, true, &blitSRV));
 
             D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
             rtvDesc.Format                = mFormatInfo.rtvFormat;
@@ -2384,7 +2460,7 @@
     if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
     {
         const TextureHelper11 *texture = nullptr;
-        ANGLE_TRY(getResource(&texture));
+        ANGLE_TRY(getResource(context, &texture));
 
         // TODO, what kind of SRV is expected here?
         const d3d11::SharedSRV srv;
@@ -2491,26 +2567,34 @@
     mTextureDepth  = depth;
 }
 
-TextureStorage11_2DArray::~TextureStorage11_2DArray()
+gl::Error TextureStorage11_2DArray::onDestroy(const gl::Context *context)
 {
-    for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++)
+    for (auto iter : mAssociatedImages)
     {
-        if (i->second)
+        if (iter.second)
         {
-            i->second->verifyAssociatedStorageValid(this);
+            iter.second->verifyAssociatedStorageValid(this);
 
             // We must let the Images recover their data before we delete it from the
             // TextureStorage.
-            i->second->recoverFromAssociatedStorage();
+            ANGLE_TRY(iter.second->recoverFromAssociatedStorage(context));
         }
     }
     mAssociatedImages.clear();
 
-    for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++)
+    for (auto iter : mRenderTargets)
     {
-        SafeDelete(i->second);
+        SafeDelete(iter.second);
     }
     mRenderTargets.clear();
+
+    delete this;
+
+    return gl::NoError();
+}
+
+TextureStorage11_2DArray::~TextureStorage11_2DArray()
+{
 }
 
 void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index)
@@ -2559,7 +2643,8 @@
 
 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
 // recover its data before ending the association.
-gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex &index,
+gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::Context *context,
+                                                           const gl::ImageIndex &index,
                                                            Image11 *incomingImage)
 {
     const GLint level       = index.mipIndex;
@@ -2576,14 +2661,15 @@
 
             // Force the image to recover from storage before its data is overwritten.
             // This will reset mAssociatedImages[level] to nullptr too.
-            ANGLE_TRY(mAssociatedImages[key]->recoverFromAssociatedStorage());
+            ANGLE_TRY(mAssociatedImages[key]->recoverFromAssociatedStorage(context));
         }
     }
 
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_2DArray::getResource(const TextureHelper11 **outResource)
+gl::Error TextureStorage11_2DArray::getResource(const gl::Context *context,
+                                                const TextureHelper11 **outResource)
 {
     // if the width, height or depth is not positive this should be treated as an incomplete texture
     // we handle that here by skipping the d3d texture creation
@@ -2612,7 +2698,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_2DArray::createSRV(int baseLevel,
+gl::Error TextureStorage11_2DArray::createSRV(const gl::Context *context,
+                                              int baseLevel,
                                               int mipLevels,
                                               DXGI_FORMAT format,
                                               const TextureHelper11 &texture,
@@ -2650,7 +2737,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index,
+gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::Context *context,
+                                                    const gl::ImageIndex &index,
                                                     RenderTargetD3D **outRT)
 {
     ASSERT(index.hasLayer());
@@ -2664,7 +2752,7 @@
     if (mRenderTargets.find(key) == mRenderTargets.end())
     {
         const TextureHelper11 *texture = nullptr;
-        ANGLE_TRY(getResource(&texture));
+        ANGLE_TRY(getResource(context, &texture));
         d3d11::SharedSRV srv;
         ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.srvFormat, &srv));
         d3d11::SharedSRV blitSRV;
@@ -2777,8 +2865,8 @@
     return gl::NoError();
 }
 
-gl::ErrorOrResult<TextureStorage11::DropStencil>
-TextureStorage11_2DArray::ensureDropStencilTexture()
+gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_2DArray::ensureDropStencilTexture(
+    const gl::Context *context)
 {
     if (mDropStencilTexture.valid())
     {
@@ -2806,7 +2894,7 @@
     std::vector<GLsizei> layerCounts(mMipLevels, mTextureDepth);
 
     ANGLE_TRY(initDropStencilTexture(
-        gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data())));
+        context, gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data())));
 
     return DropStencil::CREATED;
 }
diff --git a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
index a75ea39..b46f749 100644
--- a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
@@ -45,17 +45,22 @@
     UINT getBindFlags() const;
     UINT getMiscFlags() const;
     const d3d11::Format &getFormatSet() const;
-    gl::Error getSRVLevels(GLint baseLevel, GLint maxLevel, const d3d11::SharedSRV **outSRV);
+    gl::Error getSRVLevels(const gl::Context *context,
+                           GLint baseLevel,
+                           GLint maxLevel,
+                           const d3d11::SharedSRV **outSRV);
     gl::Error generateSwizzles(const gl::Context *context, const gl::SwizzleState &swizzleTarget);
     void markLevelDirty(int mipLevel);
     void markDirty();
 
-    gl::Error updateSubresourceLevel(const TextureHelper11 &texture,
+    gl::Error updateSubresourceLevel(const gl::Context *context,
+                                     const TextureHelper11 &texture,
                                      unsigned int sourceSubresource,
                                      const gl::ImageIndex &index,
                                      const gl::Box &copyArea);
 
-    gl::Error copySubresourceLevel(const TextureHelper11 &dstTexture,
+    gl::Error copySubresourceLevel(const gl::Context *context,
+                                   const TextureHelper11 &dstTexture,
                                    unsigned int dstSubresource,
                                    const gl::ImageIndex &index,
                                    const gl::Box &region);
@@ -69,22 +74,28 @@
     gl::Error generateMipmap(const gl::Context *context,
                              const gl::ImageIndex &sourceIndex,
                              const gl::ImageIndex &destIndex) override;
-    gl::Error copyToStorage(TextureStorage *destStorage) override;
-    gl::Error setData(const gl::ImageIndex &index,
+    gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+    gl::Error setData(const gl::Context *context,
+                      const gl::ImageIndex &index,
                       ImageD3D *image,
                       const gl::Box *destBox,
                       GLenum type,
                       const gl::PixelUnpackState &unpack,
                       const uint8_t *pixelData) override;
 
-    virtual gl::Error getSRV(const gl::TextureState &textureState, const d3d11::SharedSRV **outSRV);
+    virtual gl::Error getSRV(const gl::Context *context,
+                             const gl::TextureState &textureState,
+                             const d3d11::SharedSRV **outSRV);
     virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
-    virtual gl::Error getResource(const TextureHelper11 **outResource) = 0;
+    virtual gl::Error getResource(const gl::Context *context,
+                                  const TextureHelper11 **outResource) = 0;
     virtual void associateImage(Image11* image, const gl::ImageIndex &index) = 0;
     virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) = 0;
     virtual void verifyAssociatedImageValid(const gl::ImageIndex &index,
                                             Image11 *expectedImage) = 0;
-    virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0;
+    virtual gl::Error releaseAssociatedImage(const gl::Context *context,
+                                             const gl::ImageIndex &index,
+                                             Image11 *incomingImage) = 0;
 
   protected:
     TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags, GLenum internalFormat);
@@ -93,15 +104,19 @@
     int getLevelDepth(int mipLevel) const;
 
     // Some classes (e.g. TextureStorage11_2D) will override getMippedResource.
-    virtual gl::Error getMippedResource(const TextureHelper11 **outResource)
+    virtual gl::Error getMippedResource(const gl::Context *context,
+                                        const TextureHelper11 **outResource)
     {
-        return getResource(outResource);
+        return getResource(context, outResource);
     }
 
     virtual gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) = 0;
     virtual gl::Error getSwizzleRenderTarget(int mipLevel,
                                              const d3d11::RenderTargetView **outRTV) = 0;
-    gl::Error getSRVLevel(int mipLevel, bool blitSRV, const d3d11::SharedSRV **outSRV);
+    gl::Error getSRVLevel(const gl::Context *context,
+                          int mipLevel,
+                          bool blitSRV,
+                          const d3d11::SharedSRV **outSRV);
 
     // Get a version of a depth texture with only depth information, not stencil.
     enum DropStencil
@@ -109,11 +124,12 @@
         CREATED,
         ALREADY_EXISTS
     };
-    virtual gl::ErrorOrResult<DropStencil> ensureDropStencilTexture();
-    gl::Error initDropStencilTexture(const gl::ImageIndexIterator &it);
+    virtual gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context);
+    gl::Error initDropStencilTexture(const gl::Context *context, const gl::ImageIndexIterator &it);
 
     // The baseLevel parameter should *not* have mTopLevel applied.
-    virtual gl::Error createSRV(int baseLevel,
+    virtual gl::Error createSRV(const gl::Context *context,
+                                int baseLevel,
                                 int mipLevels,
                                 DXGI_FORMAT format,
                                 const TextureHelper11 &texture,
@@ -153,7 +169,9 @@
     };
     typedef std::map<SRVKey, d3d11::SharedSRV> SRVCache;
 
-    gl::Error getCachedOrCreateSRV(const SRVKey &key, const d3d11::SharedSRV **outSRV);
+    gl::Error getCachedOrCreateSRV(const gl::Context *context,
+                                   const SRVKey &key,
+                                   const d3d11::SharedSRV **outSRV);
 
     SRVCache mSrvCache;
     std::array<d3d11::SharedSRV, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> mLevelSRVs;
@@ -167,16 +185,23 @@
     TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false);
     ~TextureStorage11_2D() override;
 
-    gl::Error getResource(const TextureHelper11 **outResource) override;
-    gl::Error getMippedResource(const TextureHelper11 **outResource) override;
-    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+    gl::Error onDestroy(const gl::Context *context) override;
 
-    gl::Error copyToStorage(TextureStorage *destStorage) override;
+    gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
+    gl::Error getMippedResource(const gl::Context *context,
+                                const TextureHelper11 **outResource) override;
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
+
+    gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
 
     void associateImage(Image11 *image, const gl::ImageIndex &index) override;
     void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
     void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
-    gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+    gl::Error releaseAssociatedImage(const gl::Context *context,
+                                     const gl::ImageIndex &index,
+                                     Image11 *incomingImage) override;
 
     gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
 
@@ -184,12 +209,13 @@
     gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override;
     gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
 
-    gl::ErrorOrResult<DropStencil> ensureDropStencilTexture() override;
+    gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context) override;
 
     gl::Error ensureTextureExists(int mipLevels);
 
   private:
-    gl::Error createSRV(int baseLevel,
+    gl::Error createSRV(const gl::Context *context,
+                        int baseLevel,
                         int mipLevels,
                         DXGI_FORMAT format,
                         const TextureHelper11 &texture,
@@ -227,23 +253,31 @@
                               const egl::Stream::GLTextureDescription &glDesc);
     ~TextureStorage11_External() override;
 
-    gl::Error getResource(const TextureHelper11 **outResource) override;
-    gl::Error getMippedResource(const TextureHelper11 **outResource) override;
-    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+    gl::Error onDestroy(const gl::Context *context) override;
 
-    gl::Error copyToStorage(TextureStorage *destStorage) override;
+    gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
+    gl::Error getMippedResource(const gl::Context *context,
+                                const TextureHelper11 **outResource) override;
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
+
+    gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
 
     void associateImage(Image11 *image, const gl::ImageIndex &index) override;
     void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
     void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
-    gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+    gl::Error releaseAssociatedImage(const gl::Context *context,
+                                     const gl::ImageIndex &index,
+                                     Image11 *incomingImage) override;
 
   protected:
     gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override;
     gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
 
   private:
-    gl::Error createSRV(int baseLevel,
+    gl::Error createSRV(const gl::Context *context,
+                        int baseLevel,
                         int mipLevels,
                         DXGI_FORMAT format,
                         const TextureHelper11 &texture,
@@ -264,18 +298,24 @@
                               RenderTarget11 *renderTarget11);
     ~TextureStorage11_EGLImage() override;
 
-    gl::Error getResource(const TextureHelper11 **outResource) override;
-    gl::Error getSRV(const gl::TextureState &textureState,
+    gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
+    gl::Error getSRV(const gl::Context *context,
+                     const gl::TextureState &textureState,
                      const d3d11::SharedSRV **outSRV) override;
-    gl::Error getMippedResource(const TextureHelper11 **outResource) override;
-    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+    gl::Error getMippedResource(const gl::Context *context,
+                                const TextureHelper11 **outResource) override;
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
 
-    gl::Error copyToStorage(TextureStorage *destStorage) override;
+    gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
 
     void associateImage(Image11 *image, const gl::ImageIndex &index) override;
     void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
     void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
-    gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+    gl::Error releaseAssociatedImage(const gl::Context *context,
+                                     const gl::ImageIndex &index,
+                                     Image11 *incomingImage) override;
 
     gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
 
@@ -286,15 +326,16 @@
   private:
     // Check if the EGL image's render target has been updated due to orphaning and delete
     // any SRVs and other resources based on the image's old render target.
-    gl::Error checkForUpdatedRenderTarget();
+    gl::Error checkForUpdatedRenderTarget(const gl::Context *context);
 
-    gl::Error createSRV(int baseLevel,
+    gl::Error createSRV(const gl::Context *context,
+                        int baseLevel,
                         int mipLevels,
                         DXGI_FORMAT format,
                         const TextureHelper11 &texture,
                         d3d11::SharedSRV *outSRV) const override;
 
-    gl::Error getImageRenderTarget(RenderTarget11 **outRT) const;
+    gl::Error getImageRenderTarget(const gl::Context *context, RenderTarget11 **outRT) const;
 
     EGLImageD3D *mImage;
     uintptr_t mCurrentRenderTarget;
@@ -310,18 +351,25 @@
     TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
     ~TextureStorage11_Cube() override;
 
+    gl::Error onDestroy(const gl::Context *context) override;
+
     UINT getSubresourceIndex(const gl::ImageIndex &index) const override;
 
-    gl::Error getResource(const TextureHelper11 **outResource) override;
-    gl::Error getMippedResource(const TextureHelper11 **outResource) override;
-    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+    gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
+    gl::Error getMippedResource(const gl::Context *context,
+                                const TextureHelper11 **outResource) override;
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
 
-    gl::Error copyToStorage(TextureStorage *destStorage) override;
+    gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
 
     void associateImage(Image11 *image, const gl::ImageIndex &index) override;
     void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
     void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
-    gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+    gl::Error releaseAssociatedImage(const gl::Context *context,
+                                     const gl::ImageIndex &index,
+                                     Image11 *incomingImage) override;
 
     gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
 
@@ -329,12 +377,13 @@
     gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override;
     gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
 
-    gl::ErrorOrResult<DropStencil> ensureDropStencilTexture() override;
+    gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context) override;
 
     gl::Error ensureTextureExists(int mipLevels);
 
   private:
-    gl::Error createSRV(int baseLevel,
+    gl::Error createSRV(const gl::Context *context,
+                        int baseLevel,
                         int mipLevels,
                         DXGI_FORMAT format,
                         const TextureHelper11 &texture,
@@ -367,22 +416,29 @@
                         GLsizei width, GLsizei height, GLsizei depth, int levels);
     ~TextureStorage11_3D() override;
 
-    gl::Error getResource(const TextureHelper11 **outResource) override;
+    gl::Error onDestroy(const gl::Context *context) override;
+
+    gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
 
     // Handles both layer and non-layer RTs
-    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
 
     void associateImage(Image11 *image, const gl::ImageIndex &index) override;
     void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
     void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
-    gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+    gl::Error releaseAssociatedImage(const gl::Context *context,
+                                     const gl::ImageIndex &index,
+                                     Image11 *incomingImage) override;
 
   protected:
     gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override;
     gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
 
   private:
-    gl::Error createSRV(int baseLevel,
+    gl::Error createSRV(const gl::Context *context,
+                        int baseLevel,
                         int mipLevels,
                         DXGI_FORMAT format,
                         const TextureHelper11 &texture,
@@ -408,22 +464,29 @@
                              GLsizei width, GLsizei height, GLsizei depth, int levels);
     ~TextureStorage11_2DArray() override;
 
-    gl::Error getResource(const TextureHelper11 **outResource) override;
-    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+    gl::Error onDestroy(const gl::Context *context) override;
+
+    gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
 
     void associateImage(Image11 *image, const gl::ImageIndex &index) override;
     void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
     void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
-    gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+    gl::Error releaseAssociatedImage(const gl::Context *context,
+                                     const gl::ImageIndex &index,
+                                     Image11 *incomingImage) override;
 
   protected:
     gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override;
     gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
 
-    gl::ErrorOrResult<DropStencil> ensureDropStencilTexture() override;
+    gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context) override;
 
   private:
-    gl::Error createSRV(int baseLevel,
+    gl::Error createSRV(const gl::Context *context,
+                        int baseLevel,
                         int mipLevels,
                         DXGI_FORMAT format,
                         const TextureHelper11 &texture,
diff --git a/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp b/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp
index a30dd67..240d6d2 100644
--- a/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp
@@ -63,12 +63,12 @@
 {
 }
 
-void TransformFeedback11::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
+void TransformFeedback11::bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding)
 {
 }
 
 void TransformFeedback11::bindIndexedBuffer(size_t index,
-                                            const OffsetBindingPointer<gl::Buffer> &binding)
+                                            const gl::OffsetBindingPointer<gl::Buffer> &binding)
 {
     mIsDirty              = true;
     mBufferOffsets[index] = static_cast<UINT>(binding.getOffset());
diff --git a/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h b/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h
index 01879d6..8a7cdd1 100644
--- a/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h
@@ -31,8 +31,9 @@
     void pause() override;
     void resume() override;
 
-    void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
-    void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+    void bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding) override;
+    void bindIndexedBuffer(size_t index,
+                           const gl::OffsetBindingPointer<gl::Buffer> &binding) override;
 
     void onApply();
 
diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
index 00c1e20..5cb14b3 100644
--- a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
@@ -10,6 +10,7 @@
 #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
 
 #include "common/bitset_utils.h"
+#include "libANGLE/Context.h"
 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
 
@@ -30,13 +31,13 @@
     }
 }
 
-VertexArray11::~VertexArray11()
+void VertexArray11::destroy(const gl::Context *context)
 {
     for (auto &buffer : mCurrentBuffers)
     {
         if (buffer.get())
         {
-            buffer.set(nullptr);
+            buffer.set(context, nullptr);
         }
     }
 }
@@ -56,9 +57,9 @@
     }
 }
 
-void VertexArray11::flushAttribUpdates(const gl::State &state)
+void VertexArray11::flushAttribUpdates(const gl::Context *context)
 {
-    const gl::Program *program  = state.getProgram();
+    const gl::Program *program  = context->getGLState().getProgram();
     const auto &activeLocations = program->getActiveAttribLocationsMask();
 
     if (mAttribsToUpdate.any())
@@ -69,12 +70,12 @@
         for (auto toUpdateIndex : activeToUpdate)
         {
             mAttribsToUpdate.reset(toUpdateIndex);
-            updateVertexAttribStorage(toUpdateIndex);
+            updateVertexAttribStorage(context, toUpdateIndex);
         }
     }
 }
 
-void VertexArray11::updateVertexAttribStorage(size_t attribIndex)
+void VertexArray11::updateVertexAttribStorage(const gl::Context *context, size_t attribIndex)
 {
     const auto &attrib = mData.getVertexAttribute(attribIndex);
     const auto &binding = mData.getBindingFromAttribIndex(attribIndex);
@@ -131,25 +132,26 @@
             }
         }
         mOnBufferDataDirty[attribIndex].bind(newChannel);
-        mCurrentBuffers[attribIndex] = binding.getBuffer();
+        mCurrentBuffers[attribIndex].set(context, binding.getBuffer().get());
     }
 }
 
-bool VertexArray11::hasDynamicAttrib(const gl::State &state)
+bool VertexArray11::hasDynamicAttrib(const gl::Context *context)
 {
-    flushAttribUpdates(state);
+    flushAttribUpdates(context);
     return mDynamicAttribsMask.any();
 }
 
-gl::Error VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager,
-                                                      const gl::State &state,
+gl::Error VertexArray11::updateDirtyAndDynamicAttribs(const gl::Context *context,
+                                                      VertexDataManager *vertexDataManager,
                                                       GLint start,
                                                       GLsizei count,
                                                       GLsizei instances)
 {
-    flushAttribUpdates(state);
+    flushAttribUpdates(context);
 
-    const gl::Program *program  = state.getProgram();
+    const auto &glState         = context->getGLState();
+    const gl::Program *program  = glState.getProgram();
     const auto &activeLocations = program->getActiveAttribLocationsMask();
     const auto &attribs         = mData.getVertexAttributes();
     const auto &bindings        = mData.getVertexBindings();
@@ -164,7 +166,7 @@
             mAttribsToTranslate.reset(dirtyAttribIndex);
 
             auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex];
-            const auto &currentValue = state.getVertexAttribCurrentValue(dirtyAttribIndex);
+            const auto &currentValue = glState.getVertexAttribCurrentValue(dirtyAttribIndex);
 
             // Record basic attrib info
             translatedAttrib->attribute = &attribs[dirtyAttribIndex];
@@ -199,7 +201,7 @@
         for (auto dynamicAttribIndex : activeDynamicAttribs)
         {
             auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex];
-            const auto &currentValue = state.getVertexAttribCurrentValue(dynamicAttribIndex);
+            const auto &currentValue = glState.getVertexAttribCurrentValue(dynamicAttribIndex);
 
             // Record basic attrib info
             dynamicAttrib->attribute        = &attribs[dynamicAttribIndex];
diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
index 7eb453b..449ca59 100644
--- a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
@@ -22,14 +22,14 @@
 {
   public:
     VertexArray11(const gl::VertexArrayState &data);
-    ~VertexArray11() override;
+    void destroy(const gl::Context *context) override;
 
     void syncState(const gl::Context *context,
                    const gl::VertexArray::DirtyBits &dirtyBits) override;
     // This will flush any pending attrib updates and then check the dynamic attribs mask.
-    bool hasDynamicAttrib(const gl::State &state);
-    gl::Error updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager,
-                                           const gl::State &state,
+    bool hasDynamicAttrib(const gl::Context *context);
+    gl::Error updateDirtyAndDynamicAttribs(const gl::Context *context,
+                                           VertexDataManager *vertexDataManager,
                                            GLint start,
                                            GLsizei count,
                                            GLsizei instances);
@@ -41,8 +41,8 @@
     void signal(size_t channelID) override;
 
   private:
-    void updateVertexAttribStorage(size_t attribIndex);
-    void flushAttribUpdates(const gl::State &state);
+    void updateVertexAttribStorage(const gl::Context *context, size_t attribIndex);
+    void flushAttribUpdates(const gl::Context *context);
 
     std::vector<VertexStorageType> mAttributeStorageTypes;
     std::vector<TranslatedAttribute> mTranslatedAttribs;
@@ -57,7 +57,7 @@
     gl::AttributesMask mAttribsToTranslate;
 
     // We need to keep a safe pointer to the Buffer so we can attach the correct dirty callbacks.
-    std::vector<BindingPointer<gl::Buffer>> mCurrentBuffers;
+    std::vector<gl::BindingPointer<gl::Buffer>> mCurrentBuffers;
 
     std::vector<OnBufferDataDirtyBinding> mOnBufferDataDirty;
 };
diff --git a/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp b/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
index 7e566ed..dc1ae4c 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
@@ -236,7 +236,13 @@
     return gl::NoError();
 }
 
-gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level)
+gl::Error Blit9::copy2D(const gl::Context *context,
+                        const gl::Framebuffer *framebuffer,
+                        const RECT &sourceRect,
+                        GLenum destFormat,
+                        const gl::Offset &destOffset,
+                        TextureStorage *storage,
+                        GLint level)
 {
     ANGLE_TRY(initialize());
 
@@ -244,7 +250,7 @@
     ASSERT(colorbuffer);
 
     RenderTarget9 *renderTarget9 = nullptr;
-    ANGLE_TRY(colorbuffer->getRenderTarget(&renderTarget9));
+    ANGLE_TRY(colorbuffer->getRenderTarget(context, &renderTarget9));
     ASSERT(renderTarget9);
 
     IDirect3DSurface9 *source = renderTarget9->getSurface();
@@ -252,7 +258,7 @@
 
     IDirect3DSurface9 *destSurface = nullptr;
     TextureStorage9 *storage9      = GetAs<TextureStorage9>(storage);
-    gl::Error error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, true, &destSurface);
+    gl::Error error = storage9->getSurfaceLevel(context, GL_TEXTURE_2D, level, true, &destSurface);
     if (error.isError())
     {
         SafeRelease(source);
@@ -269,7 +275,14 @@
     return result;
 }
 
-gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level)
+gl::Error Blit9::copyCube(const gl::Context *context,
+                          const gl::Framebuffer *framebuffer,
+                          const RECT &sourceRect,
+                          GLenum destFormat,
+                          const gl::Offset &destOffset,
+                          TextureStorage *storage,
+                          GLenum target,
+                          GLint level)
 {
     gl::Error error = initialize();
     if (error.isError())
@@ -281,7 +294,7 @@
     ASSERT(colorbuffer);
 
     RenderTarget9 *renderTarget9 = nullptr;
-    error = colorbuffer->getRenderTarget(&renderTarget9);
+    error                        = colorbuffer->getRenderTarget(context, &renderTarget9);
     if (error.isError())
     {
         return error;
@@ -293,7 +306,7 @@
 
     IDirect3DSurface9 *destSurface = nullptr;
     TextureStorage9 *storage9      = GetAs<TextureStorage9>(storage);
-    error = storage9->getSurfaceLevel(target, level, true, &destSurface);
+    error = storage9->getSurfaceLevel(context, target, level, true, &destSurface);
     if (error.isError())
     {
         SafeRelease(source);
@@ -310,7 +323,8 @@
     return result;
 }
 
-gl::Error Blit9::copyTexture(const gl::Texture *source,
+gl::Error Blit9::copyTexture(const gl::Context *context,
+                             const gl::Texture *source,
                              GLint sourceLevel,
                              const RECT &sourceRect,
                              GLenum destFormat,
@@ -327,7 +341,7 @@
     const TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
 
     TextureStorage *sourceStorage = nullptr;
-    ANGLE_TRY(const_cast<TextureD3D *>(sourceD3D)->getNativeTexture(&sourceStorage));
+    ANGLE_TRY(const_cast<TextureD3D *>(sourceD3D)->getNativeTexture(context, &sourceStorage));
 
     TextureStorage9_2D *sourceStorage9 = GetAs<TextureStorage9_2D>(sourceStorage);
     ASSERT(sourceStorage9);
@@ -337,13 +351,15 @@
 
     ASSERT(sourceLevel == 0);
     IDirect3DBaseTexture9 *sourceTexture = nullptr;
-    ANGLE_TRY(sourceStorage9->getBaseTexture(&sourceTexture));
+    ANGLE_TRY(sourceStorage9->getBaseTexture(context, &sourceTexture));
 
     IDirect3DSurface9 *sourceSurface = nullptr;
-    ANGLE_TRY(sourceStorage9->getSurfaceLevel(GL_TEXTURE_2D, sourceLevel, true, &sourceSurface));
+    ANGLE_TRY(
+        sourceStorage9->getSurfaceLevel(context, GL_TEXTURE_2D, sourceLevel, true, &sourceSurface));
 
     IDirect3DSurface9 *destSurface = nullptr;
-    gl::Error error = destStorage9->getSurfaceLevel(destTarget, destLevel, true, &destSurface);
+    gl::Error error =
+        destStorage9->getSurfaceLevel(context, destTarget, destLevel, true, &destSurface);
     if (error.isError())
     {
         SafeRelease(sourceSurface);
diff --git a/src/libANGLE/renderer/d3d/d3d9/Blit9.h b/src/libANGLE/renderer/d3d/d3d9/Blit9.h
index 926c591..026874f 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Blit9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Blit9.h
@@ -16,6 +16,7 @@
 
 namespace gl
 {
+class Context;
 class Framebuffer;
 class Texture;
 struct Extents;
@@ -37,15 +38,23 @@
 
     // Copy from source surface to dest surface.
     // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
-    gl::Error copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level);
-    gl::Error copyCube(const gl::Framebuffer *framebuffer,
+    gl::Error copy2D(const gl::Context *context,
+                     const gl::Framebuffer *framebuffer,
+                     const RECT &sourceRect,
+                     GLenum destFormat,
+                     const gl::Offset &destOffset,
+                     TextureStorage *storage,
+                     GLint level);
+    gl::Error copyCube(const gl::Context *context,
+                       const gl::Framebuffer *framebuffer,
                        const RECT &sourceRect,
                        GLenum destFormat,
                        const gl::Offset &destOffset,
                        TextureStorage *storage,
                        GLenum target,
                        GLint level);
-    gl::Error copyTexture(const gl::Texture *source,
+    gl::Error copyTexture(const gl::Context *context,
+                          const gl::Texture *source,
                           GLint sourceLevel,
                           const RECT &sourceRect,
                           GLenum destFormat,
diff --git a/src/libANGLE/renderer/d3d/d3d9/Context9.cpp b/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
index 341bf80..6d89ad7 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
@@ -253,7 +253,7 @@
     return mRenderer->getTimestamp();
 }
 
-void Context9::onMakeCurrent(const gl::ContextState &data)
+void Context9::onMakeCurrent(const gl::Context *context)
 {
 }
 
diff --git a/src/libANGLE/renderer/d3d/d3d9/Context9.h b/src/libANGLE/renderer/d3d/d3d9/Context9.h
index 45f9bc8..f71275f 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Context9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Context9.h
@@ -123,7 +123,7 @@
     GLint64 getTimestamp() override;
 
     // Context switching
-    void onMakeCurrent(const gl::ContextState &data) override;
+    void onMakeCurrent(const gl::Context *context) override;
 
     // Caps queries
     const gl::Caps &getNativeCaps() const override;
diff --git a/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
index ef3ce2c..97ecd6c 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
@@ -35,21 +35,24 @@
 {
 }
 
-gl::Error Framebuffer9::discard(size_t, const GLenum *)
+gl::Error Framebuffer9::discard(const gl::Context *context, size_t, const GLenum *)
 {
     // Extension not implemented in D3D9 renderer
     UNREACHABLE();
     return gl::NoError();
 }
 
-gl::Error Framebuffer9::invalidate(size_t, const GLenum *)
+gl::Error Framebuffer9::invalidate(const gl::Context *context, size_t, const GLenum *)
 {
     // Shouldn't ever reach here in D3D9
     UNREACHABLE();
     return gl::NoError();
 }
 
-gl::Error Framebuffer9::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
+gl::Error Framebuffer9::invalidateSub(const gl::Context *context,
+                                      size_t,
+                                      const GLenum *,
+                                      const gl::Rectangle &)
 {
     // Shouldn't ever reach here in D3D9
     UNREACHABLE();
@@ -61,8 +64,7 @@
     const gl::FramebufferAttachment *colorAttachment        = mState.getColorAttachment(0);
     const gl::FramebufferAttachment *depthStencilAttachment = mState.getDepthOrStencilAttachment();
 
-    ANGLE_TRY(mRenderer->applyRenderTarget(context->getImplementation(), colorAttachment,
-                                           depthStencilAttachment));
+    ANGLE_TRY(mRenderer->applyRenderTarget(context, colorAttachment, depthStencilAttachment));
 
     const gl::State &glState = context->getGLState();
     float nearZ              = glState.getNearPlane();
@@ -72,10 +74,11 @@
 
     mRenderer->setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
 
-    return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment);
+    return mRenderer->clear(context, clearParams, colorAttachment, depthStencilAttachment);
 }
 
-gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area,
+gl::Error Framebuffer9::readPixelsImpl(const gl::Context *context,
+                                       const gl::Rectangle &area,
                                        GLenum format,
                                        GLenum type,
                                        size_t outputPitch,
@@ -88,11 +91,7 @@
     ASSERT(colorbuffer);
 
     RenderTarget9 *renderTarget = nullptr;
-    gl::Error error = colorbuffer->getRenderTarget(&renderTarget);
-    if (error.isError())
-    {
-        return error;
-    }
+    ANGLE_TRY(colorbuffer->getRenderTarget(context, &renderTarget));
     ASSERT(renderTarget);
 
     IDirect3DSurface9 *surface = renderTarget->getSurface();
@@ -201,7 +200,7 @@
     packParams.format      = format;
     packParams.type        = type;
     packParams.outputPitch = static_cast<GLuint>(outputPitch);
-    packParams.pack        = pack;
+    packParams.pack.copyFrom(context, pack);
 
     PackPixels(packParams, d3dFormatInfo.info(), inputPitch, source, pixels);
 
@@ -234,7 +233,7 @@
         ASSERT(readBuffer);
 
         RenderTarget9 *readRenderTarget = nullptr;
-        gl::Error error = readBuffer->getRenderTarget(&readRenderTarget);
+        gl::Error error                 = readBuffer->getRenderTarget(context, &readRenderTarget);
         if (error.isError())
         {
             return error;
@@ -245,7 +244,7 @@
         ASSERT(drawBuffer);
 
         RenderTarget9 *drawRenderTarget = nullptr;
-        error = drawBuffer->getRenderTarget(&drawRenderTarget);
+        error                           = drawBuffer->getRenderTarget(context, &drawRenderTarget);
         if (error.isError())
         {
             return error;
@@ -360,7 +359,7 @@
         ASSERT(readBuffer);
 
         RenderTarget9 *readDepthStencil = nullptr;
-        gl::Error error = readBuffer->getRenderTarget(&readDepthStencil);
+        gl::Error error                 = readBuffer->getRenderTarget(context, &readDepthStencil);
         if (error.isError())
         {
             return error;
@@ -371,7 +370,7 @@
         ASSERT(drawBuffer);
 
         RenderTarget9 *drawDepthStencil = nullptr;
-        error = drawBuffer->getRenderTarget(&drawDepthStencil);
+        error                           = drawBuffer->getRenderTarget(context, &drawDepthStencil);
         if (error.isError())
         {
             return error;
diff --git a/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
index 4e4d432..9d8d5e1 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
@@ -21,14 +21,20 @@
     Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer);
     virtual ~Framebuffer9();
 
-    gl::Error discard(size_t count, const GLenum *attachments) override;
-    gl::Error invalidate(size_t count, const GLenum *attachments) override;
-    gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
+    gl::Error discard(const gl::Context *context, size_t count, const GLenum *attachments) override;
+    gl::Error invalidate(const gl::Context *context,
+                         size_t count,
+                         const GLenum *attachments) override;
+    gl::Error invalidateSub(const gl::Context *context,
+                            size_t count,
+                            const GLenum *attachments,
+                            const gl::Rectangle &area) override;
 
   private:
     gl::Error clearImpl(const gl::Context *context, const ClearParameters &clearParams) override;
 
-    gl::Error readPixelsImpl(const gl::Rectangle &area,
+    gl::Error readPixelsImpl(const gl::Context *context,
+                             const gl::Rectangle &area,
                              GLenum format,
                              GLenum type,
                              size_t outputPitch,
diff --git a/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
index 07e973a..089414b 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
@@ -335,11 +335,13 @@
     return gl::NoError();
 }
 
-gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level)
+gl::Error Image9::setManagedSurface2D(const gl::Context *context,
+                                      TextureStorage *storage,
+                                      int level)
 {
     IDirect3DSurface9 *surface = nullptr;
     TextureStorage9 *storage9  = GetAs<TextureStorage9>(storage);
-    gl::Error error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, false, &surface);
+    gl::Error error = storage9->getSurfaceLevel(context, GL_TEXTURE_2D, level, false, &surface);
     if (error.isError())
     {
         return error;
@@ -347,12 +349,15 @@
     return setManagedSurface(surface);
 }
 
-gl::Error Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level)
+gl::Error Image9::setManagedSurfaceCube(const gl::Context *context,
+                                        TextureStorage *storage,
+                                        int face,
+                                        int level)
 {
     IDirect3DSurface9 *surface = nullptr;
     TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
-    gl::Error error =
-        storage9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false, &surface);
+    gl::Error error = storage9->getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face,
+                                                level, false, &surface);
     if (error.isError())
     {
         return error;
@@ -385,7 +390,10 @@
     return gl::NoError();
 }
 
-gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
+gl::Error Image9::copyToStorage(const gl::Context *context,
+                                TextureStorage *storage,
+                                const gl::ImageIndex &index,
+                                const gl::Box &region)
 {
     gl::Error error = createSurface();
     if (error.isError())
@@ -399,7 +407,8 @@
 
     if (index.type == GL_TEXTURE_2D)
     {
-        error = storage9->getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, true, &destSurface);
+        error =
+            storage9->getSurfaceLevel(context, GL_TEXTURE_2D, index.mipIndex, true, &destSurface);
         if (error.isError())
         {
             return error;
@@ -408,7 +417,7 @@
     else
     {
         ASSERT(gl::IsCubeMapTextureTarget(index.type));
-        error = storage9->getSurfaceLevel(index.type, index.mipIndex, true, &destSurface);
+        error = storage9->getSurfaceLevel(context, index.type, index.mipIndex, true, &destSurface);
         if (error.isError())
         {
             return error;
@@ -483,7 +492,8 @@
 
 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
 // into the target pixel rectangle.
-gl::Error Image9::loadData(const gl::Box &area,
+gl::Error Image9::loadData(const gl::Context *context,
+                           const gl::Box &area,
                            const gl::PixelUnpackState &unpack,
                            GLenum type,
                            const void *input,
@@ -526,7 +536,9 @@
     return gl::NoError();
 }
 
-gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input)
+gl::Error Image9::loadCompressedData(const gl::Context *context,
+                                     const gl::Box &area,
+                                     const void *input)
 {
     // 3D textures are not supported by the D3D9 backend.
     ASSERT(area.z == 0 && area.depth == 1);
@@ -804,10 +816,12 @@
     return gl::NoError();
 }
 
-gl::Error Image9::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source)
+gl::Error Image9::copyFromTexStorage(const gl::Context *context,
+                                     const gl::ImageIndex &imageIndex,
+                                     TextureStorage *source)
 {
     RenderTargetD3D *renderTarget = nullptr;
-    gl::Error error = source->getRenderTarget(imageIndex, &renderTarget);
+    gl::Error error               = source->getRenderTarget(context, imageIndex, &renderTarget);
     if (error.isError())
     {
         return error;
@@ -817,7 +831,8 @@
     return copyFromRTInternal(gl::Offset(), sourceArea, renderTarget);
 }
 
-gl::Error Image9::copyFromFramebuffer(const gl::Offset &destOffset,
+gl::Error Image9::copyFromFramebuffer(const gl::Context *context,
+                                      const gl::Offset &destOffset,
                                       const gl::Rectangle &sourceArea,
                                       const gl::Framebuffer *source)
 {
@@ -825,7 +840,7 @@
     ASSERT(srcAttachment);
 
     RenderTargetD3D *renderTarget = nullptr;
-    gl::Error error = srcAttachment->getRenderTarget(&renderTarget);
+    gl::Error error               = srcAttachment->getRenderTarget(context, &renderTarget);
     if (error.isError())
     {
         return error;
diff --git a/src/libANGLE/renderer/d3d/d3d9/Image9.h b/src/libANGLE/renderer/d3d/d3d9/Image9.h
index 068a67f..7ece2aa 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Image9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Image9.h
@@ -38,19 +38,33 @@
 
     virtual bool isDirty() const;
 
-    virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level);
-    virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level);
-    virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+    gl::Error setManagedSurface2D(const gl::Context *context,
+                                  TextureStorage *storage,
+                                  int level) override;
+    gl::Error setManagedSurfaceCube(const gl::Context *context,
+                                    TextureStorage *storage,
+                                    int face,
+                                    int level) override;
+    gl::Error copyToStorage(const gl::Context *context,
+                            TextureStorage *storage,
+                            const gl::ImageIndex &index,
+                            const gl::Box &region) override;
 
-    gl::Error loadData(const gl::Box &area,
+    gl::Error loadData(const gl::Context *context,
+                       const gl::Box &area,
                        const gl::PixelUnpackState &unpack,
                        GLenum type,
                        const void *input,
                        bool applySkipImages) override;
-    gl::Error loadCompressedData(const gl::Box &area, const void *input) override;
+    gl::Error loadCompressedData(const gl::Context *context,
+                                 const gl::Box &area,
+                                 const void *input) override;
 
-    gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override;
-    gl::Error copyFromFramebuffer(const gl::Offset &destOffset,
+    gl::Error copyFromTexStorage(const gl::Context *context,
+                                 const gl::ImageIndex &imageIndex,
+                                 TextureStorage *source) override;
+    gl::Error copyFromFramebuffer(const gl::Context *context,
+                                  const gl::Offset &destOffset,
                                   const gl::Rectangle &sourceArea,
                                   const gl::Framebuffer *source) override;
 
diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
index 1d86042..ea6d943 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -925,7 +925,8 @@
     return gl::InternalError();
 }
 
-gl::Error Renderer9::setSamplerState(gl::SamplerType type,
+gl::Error Renderer9::setSamplerState(const gl::Context *context,
+                                     gl::SamplerType type,
                                      int index,
                                      gl::Texture *texture,
                                      const gl::SamplerState &samplerState)
@@ -937,11 +938,7 @@
     TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
 
     TextureStorage *storage = nullptr;
-    gl::Error error         = textureD3D->getNativeTexture(&storage);
-    if (error.isError())
-    {
-        return error;
-    }
+    ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
 
     // Storage should exist, texture should be complete
     ASSERT(storage);
@@ -986,7 +983,10 @@
     return gl::NoError();
 }
 
-gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
+gl::Error Renderer9::setTexture(const gl::Context *context,
+                                gl::SamplerType type,
+                                int index,
+                                gl::Texture *texture)
 {
     int d3dSamplerOffset              = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
     int d3dSampler                    = index + d3dSamplerOffset;
@@ -1001,21 +1001,13 @@
         TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
 
         TextureStorage *texStorage = nullptr;
-        gl::Error error            = textureImpl->getNativeTexture(&texStorage);
-        if (error.isError())
-        {
-            return error;
-        }
+        ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
 
         // Texture should be complete and have a storage
         ASSERT(texStorage);
 
         TextureStorage9 *storage9 = GetAs<TextureStorage9>(texStorage);
-        error                     = storage9->getBaseTexture(&d3dTexture);
-        if (error.isError())
-        {
-            return error;
-        }
+        ANGLE_TRY(storage9->getBaseTexture(context, &d3dTexture));
 
         // If we get NULL back from getBaseTexture here, something went wrong
         // in the texture class and we're unexpectedly missing the d3d texture
@@ -1043,7 +1035,7 @@
     return gl::NoError();
 }
 
-gl::Error Renderer9::updateState(Context9 *context, GLenum drawMode)
+gl::Error Renderer9::updateState(const gl::Context *context, GLenum drawMode)
 {
     const auto &data    = context->getContextState();
     const auto &glState = data.getState();
@@ -1072,7 +1064,7 @@
     {
         ASSERT(firstColorAttachment->isAttached());
         RenderTarget9 *renderTarget = nullptr;
-        ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
+        ANGLE_TRY(firstColorAttachment->getRenderTarget(context, &renderTarget));
         samples = renderTarget->getSamples();
     }
     gl::RasterizerState rasterizer = glState.getRasterizerState();
@@ -1080,7 +1072,7 @@
     rasterizer.multiSample         = (samples != 0);
 
     unsigned int mask = GetBlendSampleMask(data, samples);
-    ANGLE_TRY(setBlendDepthRasterStates(data, mask));
+    ANGLE_TRY(setBlendDepthRasterStates(context, mask));
 
     mStateManager.resetDirtyBits();
 
@@ -1092,9 +1084,9 @@
     mStateManager.setScissorState(scissor, enabled);
 }
 
-gl::Error Renderer9::setBlendDepthRasterStates(const gl::ContextState &glData, GLenum drawMode)
+gl::Error Renderer9::setBlendDepthRasterStates(const gl::Context *context, GLenum drawMode)
 {
-    const auto &glState  = glData.getState();
+    const auto &glState  = context->getGLState();
     auto drawFramebuffer = glState.getDrawFramebuffer();
     ASSERT(!drawFramebuffer->hasAnyDirtyBit());
     // Since framebuffer->getSamples will return the original samples which may be different with
@@ -1106,14 +1098,14 @@
     {
         ASSERT(firstColorAttachment->isAttached());
         RenderTarget9 *renderTarget = nullptr;
-        ANGLE_TRY(firstColorAttachment->getRenderTarget(&renderTarget));
+        ANGLE_TRY(firstColorAttachment->getRenderTarget(context, &renderTarget));
         samples = renderTarget->getSamples();
     }
     gl::RasterizerState rasterizer = glState.getRasterizerState();
     rasterizer.pointDrawMode       = (drawMode == GL_POINTS);
     rasterizer.multiSample         = (samples != 0);
 
-    unsigned int mask = GetBlendSampleMask(glData, samples);
+    unsigned int mask = GetBlendSampleMask(context->getContextState(), samples);
     return mStateManager.setBlendDepthRasterStates(glState, mask);
 }
 
@@ -1168,7 +1160,7 @@
     return mPrimitiveCount > 0;
 }
 
-gl::Error Renderer9::getNullColorbuffer(GLImplFactory *implFactory,
+gl::Error Renderer9::getNullColorbuffer(const gl::Context *context,
                                         const gl::FramebufferAttachment *depthbuffer,
                                         const gl::FramebufferAttachment **outColorBuffer)
 {
@@ -1189,8 +1181,10 @@
         }
     }
 
+    auto *implFactory = context->getImplementation();
+
     gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(implFactory->createRenderbuffer(), 0);
-    gl::Error error = nullRenderbuffer->setStorage(GL_NONE, size.width, size.height);
+    gl::Error error = nullRenderbuffer->setStorage(context, GL_NONE, size.width, size.height);
     if (error.isError())
     {
         SafeDelete(nullRenderbuffer);
@@ -1198,7 +1192,7 @@
     }
 
     gl::FramebufferAttachment *nullbuffer = new gl::FramebufferAttachment(
-        GL_RENDERBUFFER, GL_NONE, gl::ImageIndex::MakeInvalid(), nullRenderbuffer);
+        context, GL_RENDERBUFFER, GL_NONE, gl::ImageIndex::MakeInvalid(), nullRenderbuffer);
 
     // add nullbuffer to the cache
     NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0];
@@ -1220,22 +1214,17 @@
     return gl::NoError();
 }
 
-gl::Error Renderer9::applyRenderTarget(GLImplFactory *implFactory,
+gl::Error Renderer9::applyRenderTarget(const gl::Context *context,
                                        const gl::FramebufferAttachment *colorAttachment,
                                        const gl::FramebufferAttachment *depthStencilAttachment)
 {
     const gl::FramebufferAttachment *renderAttachment = colorAttachment;
-    gl::Error error(gl::NoError());
 
     // if there is no color attachment we must synthesize a NULL colorattachment
     // to keep the D3D runtime happy.  This should only be possible if depth texturing.
     if (renderAttachment == nullptr)
     {
-        error = getNullColorbuffer(implFactory, depthStencilAttachment, &renderAttachment);
-        if (error.isError())
-        {
-            return error;
-        }
+        ANGLE_TRY(getNullColorbuffer(context, depthStencilAttachment, &renderAttachment));
     }
     ASSERT(renderAttachment != nullptr);
 
@@ -1244,11 +1233,7 @@
     D3DFORMAT renderTargetFormat = D3DFMT_UNKNOWN;
 
     RenderTarget9 *renderTarget = nullptr;
-    error                       = renderAttachment->getRenderTarget(&renderTarget);
-    if (error.isError())
-    {
-        return error;
-    }
+    ANGLE_TRY(renderAttachment->getRenderTarget(context, &renderTarget));
     ASSERT(renderTarget);
 
     bool renderTargetChanged        = false;
@@ -1275,11 +1260,7 @@
 
     if (depthStencilAttachment != nullptr)
     {
-        error = depthStencilAttachment->getRenderTarget(&depthStencilRenderTarget);
-        if (error.isError())
-        {
-            return error;
-        }
+        ANGLE_TRY(depthStencilAttachment->getRenderTarget(context, &depthStencilRenderTarget));
         ASSERT(depthStencilRenderTarget);
 
         depthStencilSerial = depthStencilRenderTarget->getSerial();
@@ -1325,10 +1306,10 @@
     return gl::NoError();
 }
 
-gl::Error Renderer9::applyRenderTarget(GLImplFactory *implFactory,
+gl::Error Renderer9::applyRenderTarget(const gl::Context *context,
                                        const gl::Framebuffer *framebuffer)
 {
-    return applyRenderTarget(implFactory, framebuffer->getColorbuffer(0),
+    return applyRenderTarget(context, framebuffer->getColorbuffer(0),
                              framebuffer->getDepthOrStencilbuffer());
 }
 
@@ -1944,7 +1925,8 @@
     applyUniformnfv(targetUniform, (GLfloat *)vector);
 }
 
-gl::Error Renderer9::clear(const ClearParameters &clearParams,
+gl::Error Renderer9::clear(const gl::Context *context,
+                           const ClearParameters &clearParams,
                            const gl::FramebufferAttachment *colorBuffer,
                            const gl::FramebufferAttachment *depthStencilBuffer)
 {
@@ -1976,7 +1958,7 @@
         ASSERT(depthStencilBuffer != nullptr);
 
         RenderTargetD3D *stencilRenderTarget = nullptr;
-        gl::Error error = depthStencilBuffer->getRenderTarget(&stencilRenderTarget);
+        gl::Error error = depthStencilBuffer->getRenderTarget(context, &stencilRenderTarget);
         if (error.isError())
         {
             return error;
@@ -2001,7 +1983,7 @@
         ASSERT(colorBuffer != nullptr);
 
         RenderTargetD3D *colorRenderTarget = nullptr;
-        gl::Error error                    = colorBuffer->getRenderTarget(&colorRenderTarget);
+        gl::Error error = colorBuffer->getRenderTarget(context, &colorRenderTarget);
         if (error.isError())
         {
             return error;
@@ -2258,6 +2240,10 @@
 
     for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
     {
+        if (mNullColorbufferCache[i].buffer)
+        {
+            mNullColorbufferCache[i].buffer->detach(mDisplay->getProxyContext());
+        }
         SafeDelete(mNullColorbufferCache[i].buffer);
     }
 }
@@ -2523,7 +2509,7 @@
     rect.right  = sourceRect.x + sourceRect.width;
     rect.bottom = sourceRect.y + sourceRect.height;
 
-    return mBlit->copy2D(framebuffer, rect, destFormat, destOffset, storage, level);
+    return mBlit->copy2D(context, framebuffer, rect, destFormat, destOffset, storage, level);
 }
 
 gl::Error Renderer9::copyImageCube(const gl::Context *context,
@@ -2541,7 +2527,8 @@
     rect.right  = sourceRect.x + sourceRect.width;
     rect.bottom = sourceRect.y + sourceRect.height;
 
-    return mBlit->copyCube(framebuffer, rect, destFormat, destOffset, storage, target, level);
+    return mBlit->copyCube(context, framebuffer, rect, destFormat, destOffset, storage, target,
+                           level);
 }
 
 gl::Error Renderer9::copyImage3D(const gl::Context *context,
@@ -2589,12 +2576,13 @@
     rect.right  = sourceRect.x + sourceRect.width;
     rect.bottom = sourceRect.y + sourceRect.height;
 
-    return mBlit->copyTexture(source, sourceLevel, rect, destFormat, destOffset, storage,
+    return mBlit->copyTexture(context, source, sourceLevel, rect, destFormat, destOffset, storage,
                               destTarget, destLevel, unpackFlipY, unpackPremultiplyAlpha,
                               unpackUnmultiplyAlpha);
 }
 
-gl::Error Renderer9::copyCompressedTexture(const gl::Texture *source,
+gl::Error Renderer9::copyCompressedTexture(const gl::Context *context,
+                                           const gl::Texture *source,
                                            GLint sourceLevel,
                                            TextureStorage *storage,
                                            GLint destLevel)
@@ -2914,21 +2902,23 @@
     return new Image9(this);
 }
 
-gl::Error Renderer9::generateMipmap(ImageD3D *dest, ImageD3D *src)
+gl::Error Renderer9::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
 {
     Image9 *src9 = GetAs<Image9>(src);
     Image9 *dst9 = GetAs<Image9>(dest);
     return Image9::generateMipmap(dst9, src9);
 }
 
-gl::Error Renderer9::generateMipmapUsingD3D(TextureStorage *storage,
+gl::Error Renderer9::generateMipmapUsingD3D(const gl::Context *context,
+                                            TextureStorage *storage,
                                             const gl::TextureState &textureState)
 {
     UNREACHABLE();
     return gl::NoError();
 }
 
-gl::Error Renderer9::copyImage(ImageD3D *dest,
+gl::Error Renderer9::copyImage(const gl::Context *context,
+                               ImageD3D *dest,
                                ImageD3D *source,
                                const gl::Rectangle &sourceRect,
                                const gl::Offset &destOffset,
@@ -3078,16 +3068,15 @@
     return d3d9::GenerateWorkarounds();
 }
 
-gl::Error Renderer9::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd)
+gl::Error Renderer9::clearTextures(const gl::Context *context,
+                                   gl::SamplerType samplerType,
+                                   size_t rangeStart,
+                                   size_t rangeEnd)
 {
     // TODO(jmadill): faster way?
     for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; samplerIndex++)
     {
-        gl::Error error = setTexture(samplerType, static_cast<int>(samplerIndex), nullptr);
-        if (error.isError())
-        {
-            return error;
-        }
+        ANGLE_TRY(setTexture(context, samplerType, static_cast<int>(samplerIndex), nullptr));
     }
 
     return gl::NoError();
@@ -3139,7 +3128,7 @@
         return gl::NoError();
     }
 
-    ANGLE_TRY(updateState(GetImplAs<Context9>(context), mode));
+    ANGLE_TRY(updateState(context, mode));
 
     TranslatedIndexData indexInfo;
     indexInfo.indexRange = indexRange;
@@ -3187,7 +3176,7 @@
         return gl::NoError();
     }
 
-    ANGLE_TRY(updateState(GetImplAs<Context9>(context), mode));
+    ANGLE_TRY(updateState(context, mode));
     ANGLE_TRY(applyTransformFeedbackBuffers(data.getState()));
     ANGLE_TRY(applyVertexBuffer(data.getState(), mode, first, count, instances, nullptr));
     ANGLE_TRY(applyTextures(context));
diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
index 0e89e96..b659008 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
@@ -119,17 +119,21 @@
                               DWORD Usage,
                               D3DFORMAT Format,
                               IDirect3DIndexBuffer9 **ppIndexBuffer);
-    gl::Error setSamplerState(gl::SamplerType type,
+    gl::Error setSamplerState(const gl::Context *context,
+                              gl::SamplerType type,
                               int index,
                               gl::Texture *texture,
                               const gl::SamplerState &sampler) override;
-    gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) override;
+    gl::Error setTexture(const gl::Context *context,
+                         gl::SamplerType type,
+                         int index,
+                         gl::Texture *texture) override;
 
     gl::Error setUniformBuffers(const gl::ContextState &data,
                                 const std::vector<GLint> &vertexUniformBuffers,
                                 const std::vector<GLint> &fragmentUniformBuffers) override;
 
-    gl::Error updateState(Context9 *context, GLenum drawMode);
+    gl::Error updateState(const gl::Context *context, GLenum drawMode);
 
     void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
     void setViewport(const gl::Rectangle &viewport,
@@ -139,8 +143,8 @@
                      GLenum frontFace,
                      bool ignoreViewport);
 
-    gl::Error applyRenderTarget(GLImplFactory *implFactory, const gl::Framebuffer *frameBuffer);
-    gl::Error applyRenderTarget(GLImplFactory *implFactory,
+    gl::Error applyRenderTarget(const gl::Context *context, const gl::Framebuffer *frameBuffer);
+    gl::Error applyRenderTarget(const gl::Context *context,
                                 const gl::FramebufferAttachment *colorAttachment,
                                 const gl::FramebufferAttachment *depthStencilAttachment);
     gl::Error applyUniforms(const ProgramD3D &programD3D,
@@ -162,7 +166,8 @@
 
     gl::Error applyTransformFeedbackBuffers(const gl::State &state);
 
-    gl::Error clear(const ClearParameters &clearParams,
+    gl::Error clear(const gl::Context *context,
+                    const ClearParameters &clearParams,
                     const gl::FramebufferAttachment *colorBuffer,
                     const gl::FramebufferAttachment *depthStencilBuffer);
 
@@ -235,7 +240,8 @@
                           bool unpackFlipY,
                           bool unpackPremultiplyAlpha,
                           bool unpackUnmultiplyAlpha) override;
-    gl::Error copyCompressedTexture(const gl::Texture *source,
+    gl::Error copyCompressedTexture(const gl::Context *context,
+                                    const gl::Texture *source,
                                     GLint sourceLevel,
                                     TextureStorage *storage,
                                     GLint destLevel) override;
@@ -268,10 +274,12 @@
 
     // Image operations
     ImageD3D *createImage() override;
-    gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
-    gl::Error generateMipmapUsingD3D(TextureStorage *storage,
+    gl::Error generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *source) override;
+    gl::Error generateMipmapUsingD3D(const gl::Context *context,
+                                     TextureStorage *storage,
                                      const gl::TextureState &textureState) override;
-    gl::Error copyImage(ImageD3D *dest,
+    gl::Error copyImage(const gl::Context *context,
+                        ImageD3D *dest,
                         ImageD3D *source,
                         const gl::Rectangle &sourceRect,
                         const gl::Offset &destOffset,
@@ -381,7 +389,8 @@
                                    const std::vector<D3DUniform *> &uniformArray) override;
 
   protected:
-    gl::Error clearTextures(gl::SamplerType samplerType,
+    gl::Error clearTextures(const gl::Context *context,
+                            gl::SamplerType samplerType,
                             size_t rangeStart,
                             size_t rangeEnd) override;
 
@@ -408,7 +417,7 @@
 
     angle::WorkaroundsD3D generateWorkarounds() const override;
 
-    gl::Error setBlendDepthRasterStates(const gl::ContextState &glData, GLenum drawMode);
+    gl::Error setBlendDepthRasterStates(const gl::Context *context, GLenum drawMode);
 
     void release();
 
@@ -429,7 +438,7 @@
 
     gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB);
 
-    gl::Error getNullColorbuffer(GLImplFactory *implFactory,
+    gl::Error getNullColorbuffer(const gl::Context *context,
                                  const gl::FramebufferAttachment *depthbuffer,
                                  const gl::FramebufferAttachment **outColorBuffer);
 
diff --git a/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp b/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
index 3c4dd86..9bcaeb6 100644
--- a/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
@@ -93,8 +93,13 @@
     return static_cast<int>(mMipLevels) - mTopLevel;
 }
 
-gl::Error TextureStorage9::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
-                                   const gl::PixelUnpackState &unpack, const uint8_t *pixelData)
+gl::Error TextureStorage9::setData(const gl::Context *context,
+                                   const gl::ImageIndex &index,
+                                   ImageD3D *image,
+                                   const gl::Box *destBox,
+                                   GLenum type,
+                                   const gl::PixelUnpackState &unpack,
+                                   const uint8_t *pixelData)
 {
     UNREACHABLE();
     return gl::InternalError();
@@ -147,7 +152,8 @@
 
 // Increments refcount on surface.
 // caller must Release() the returned surface
-gl::Error TextureStorage9_2D::getSurfaceLevel(GLenum target,
+gl::Error TextureStorage9_2D::getSurfaceLevel(const gl::Context *context,
+                                              GLenum target,
                                               int level,
                                               bool dirty,
                                               IDirect3DSurface9 **outSurface)
@@ -155,7 +161,7 @@
     ASSERT(target == GL_TEXTURE_2D);
 
     IDirect3DBaseTexture9 *baseTexture = nullptr;
-    gl::Error error = getBaseTexture(&baseTexture);
+    gl::Error error                    = getBaseTexture(context, &baseTexture);
     if (error.isError())
     {
         return error;
@@ -181,21 +187,23 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureStorage9_2D::getRenderTarget(const gl::Context *context,
+                                              const gl::ImageIndex &index,
+                                              RenderTargetD3D **outRT)
 {
     ASSERT(index.mipIndex < getLevelCount());
 
     if (!mRenderTargets[index.mipIndex] && isRenderTarget())
     {
         IDirect3DBaseTexture9 *baseTexture = nullptr;
-        gl::Error error = getBaseTexture(&baseTexture);
+        gl::Error error                    = getBaseTexture(context, &baseTexture);
         if (error.isError())
         {
             return error;
         }
 
         IDirect3DSurface9 *surface = nullptr;
-        error = getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, false, &surface);
+        error = getSurfaceLevel(context, GL_TEXTURE_2D, index.mipIndex, false, &surface);
         if (error.isError())
         {
             return error;
@@ -221,14 +229,14 @@
                                              const gl::ImageIndex &destIndex)
 {
     IDirect3DSurface9 *upper = nullptr;
-    gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, sourceIndex.mipIndex, false, &upper);
+    gl::Error error = getSurfaceLevel(context, GL_TEXTURE_2D, sourceIndex.mipIndex, false, &upper);
     if (error.isError())
     {
         return error;
     }
 
     IDirect3DSurface9 *lower = nullptr;
-    error = getSurfaceLevel(GL_TEXTURE_2D, destIndex.mipIndex, true, &lower);
+    error = getSurfaceLevel(context, GL_TEXTURE_2D, destIndex.mipIndex, true, &lower);
     if (error.isError())
     {
         SafeRelease(upper);
@@ -244,7 +252,8 @@
     return error;
 }
 
-gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
+gl::Error TextureStorage9_2D::getBaseTexture(const gl::Context *context,
+                                             IDirect3DBaseTexture9 **outTexture)
 {
     // if the width or height is not positive this should be treated as an incomplete texture
     // we handle that here by skipping the d3d texture creation
@@ -270,7 +279,7 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage9_2D::copyToStorage(const gl::Context *context, TextureStorage *destStorage)
 {
     ASSERT(destStorage);
 
@@ -280,14 +289,14 @@
     for (int i = 0; i < levels; ++i)
     {
         IDirect3DSurface9 *srcSurf = nullptr;
-        gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, i, false, &srcSurf);
+        gl::Error error            = getSurfaceLevel(context, GL_TEXTURE_2D, i, false, &srcSurf);
         if (error.isError())
         {
             return error;
         }
 
         IDirect3DSurface9 *dstSurf = nullptr;
-        error = dest9->getSurfaceLevel(GL_TEXTURE_2D, i, true, &dstSurf);
+        error = dest9->getSurfaceLevel(context, GL_TEXTURE_2D, i, true, &dstSurf);
         if (error.isError())
         {
             SafeRelease(srcSurf);
@@ -325,7 +334,8 @@
 {
 }
 
-gl::Error TextureStorage9_EGLImage::getSurfaceLevel(GLenum target,
+gl::Error TextureStorage9_EGLImage::getSurfaceLevel(const gl::Context *context,
+                                                    GLenum target,
                                                     int level,
                                                     bool,
                                                     IDirect3DSurface9 **outSurface)
@@ -334,7 +344,7 @@
     ASSERT(level == 0);
 
     RenderTargetD3D *renderTargetD3D = nullptr;
-    gl::Error error = mImage->getRenderTarget(&renderTargetD3D);
+    gl::Error error                  = mImage->getRenderTarget(context, &renderTargetD3D);
     if (error.isError())
     {
         return error;
@@ -346,19 +356,21 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage9_EGLImage::getRenderTarget(const gl::ImageIndex &index,
+gl::Error TextureStorage9_EGLImage::getRenderTarget(const gl::Context *context,
+                                                    const gl::ImageIndex &index,
                                                     RenderTargetD3D **outRT)
 {
     ASSERT(!index.hasLayer());
     ASSERT(index.mipIndex == 0);
 
-    return mImage->getRenderTarget(outRT);
+    return mImage->getRenderTarget(context, outRT);
 }
 
-gl::Error TextureStorage9_EGLImage::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
+gl::Error TextureStorage9_EGLImage::getBaseTexture(const gl::Context *context,
+                                                   IDirect3DBaseTexture9 **outTexture)
 {
     RenderTargetD3D *renderTargetD3D = nullptr;
-    gl::Error error = mImage->getRenderTarget(&renderTargetD3D);
+    gl::Error error                  = mImage->getRenderTarget(context, &renderTargetD3D);
     if (error.isError())
     {
         return error;
@@ -379,7 +391,8 @@
     return gl::InternalError();
 }
 
-gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage9_EGLImage::copyToStorage(const gl::Context *context,
+                                                  TextureStorage *destStorage)
 {
     ASSERT(destStorage);
     ASSERT(getLevelCount() == 1);
@@ -387,7 +400,7 @@
     TextureStorage9 *dest9 = GetAs<TextureStorage9>(destStorage);
 
     IDirect3DBaseTexture9 *destBaseTexture9 = nullptr;
-    gl::Error error = dest9->getBaseTexture(&destBaseTexture9);
+    gl::Error error                         = dest9->getBaseTexture(context, &destBaseTexture9);
     if (error.isError())
     {
         return error;
@@ -404,7 +417,7 @@
     }
 
     RenderTargetD3D *sourceRenderTarget = nullptr;
-    error = mImage->getRenderTarget(&sourceRenderTarget);
+    error                               = mImage->getRenderTarget(context, &sourceRenderTarget);
     if (error.isError())
     {
         SafeRelease(destSurface);
@@ -462,13 +475,14 @@
 
 // Increments refcount on surface.
 // caller must Release() the returned surface
-gl::Error TextureStorage9_Cube::getSurfaceLevel(GLenum target,
+gl::Error TextureStorage9_Cube::getSurfaceLevel(const gl::Context *context,
+                                                GLenum target,
                                                 int level,
                                                 bool dirty,
                                                 IDirect3DSurface9 **outSurface)
 {
     IDirect3DBaseTexture9 *baseTexture = nullptr;
-    gl::Error error = getBaseTexture(&baseTexture);
+    gl::Error error                    = getBaseTexture(context, &baseTexture);
     if (error.isError())
     {
         return error;
@@ -495,7 +509,9 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureStorage9_Cube::getRenderTarget(const gl::Context *context,
+                                                const gl::ImageIndex &index,
+                                                RenderTargetD3D **outRT)
 {
     ASSERT(outRT);
     ASSERT(index.mipIndex == 0);
@@ -504,14 +520,14 @@
     if (mRenderTarget[index.layerIndex] == nullptr && isRenderTarget())
     {
         IDirect3DBaseTexture9 *baseTexture = nullptr;
-        gl::Error error = getBaseTexture(&baseTexture);
+        gl::Error error                    = getBaseTexture(context, &baseTexture);
         if (error.isError())
         {
             return error;
         }
 
         IDirect3DSurface9 *surface = nullptr;
-        error = getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex,
+        error = getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex,
                                 mTopLevel + index.mipIndex, false, &surface);
         if (error.isError())
         {
@@ -533,14 +549,15 @@
                                                const gl::ImageIndex &destIndex)
 {
     IDirect3DSurface9 *upper = nullptr;
-    gl::Error error = getSurfaceLevel(sourceIndex.type, sourceIndex.mipIndex, false, &upper);
+    gl::Error error =
+        getSurfaceLevel(context, sourceIndex.type, sourceIndex.mipIndex, false, &upper);
     if (error.isError())
     {
         return error;
     }
 
     IDirect3DSurface9 *lower = nullptr;
-    error = getSurfaceLevel(destIndex.type, destIndex.mipIndex, true, &lower);
+    error = getSurfaceLevel(context, destIndex.type, destIndex.mipIndex, true, &lower);
     if (error.isError())
     {
         SafeRelease(upper);
@@ -556,7 +573,8 @@
     return error;
 }
 
-gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
+gl::Error TextureStorage9_Cube::getBaseTexture(const gl::Context *context,
+                                               IDirect3DBaseTexture9 **outTexture)
 {
     // if the size is not positive this should be treated as an incomplete texture
     // we handle that here by skipping the d3d texture creation
@@ -582,7 +600,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage9_Cube::copyToStorage(const gl::Context *context,
+                                              TextureStorage *destStorage)
 {
     ASSERT(destStorage);
 
@@ -595,14 +614,15 @@
         {
             IDirect3DSurface9 *srcSurf = nullptr;
             gl::Error error =
-                getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf);
+                getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf);
             if (error.isError())
             {
                 return error;
             }
 
             IDirect3DSurface9 *dstSurf = nullptr;
-            error = dest9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf);
+            error = dest9->getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true,
+                                           &dstSurf);
             if (error.isError())
             {
                 SafeRelease(srcSurf);
diff --git a/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h b/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
index 0f81373..a33d096 100644
--- a/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
@@ -32,12 +32,16 @@
     D3DPOOL getPool() const;
     DWORD getUsage() const;
 
-    virtual gl::Error getSurfaceLevel(GLenum target,
+    virtual gl::Error getSurfaceLevel(const gl::Context *context,
+                                      GLenum target,
                                       int level,
                                       bool dirty,
                                       IDirect3DSurface9 **outSurface) = 0;
-    virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) = 0;
-    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
+    virtual gl::Error getBaseTexture(const gl::Context *context,
+                                     IDirect3DBaseTexture9 **outTexture) = 0;
+    virtual gl::Error getRenderTarget(const gl::Context *context,
+                                      const gl::ImageIndex &index,
+                                      RenderTargetD3D **outRT) = 0;
 
     virtual int getTopLevel() const;
     virtual bool isRenderTarget() const;
@@ -45,8 +49,13 @@
     bool supportsNativeMipmapFunction() const override;
     virtual int getLevelCount() const;
 
-    virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
-                              const gl::PixelUnpackState &unpack, const uint8_t *pixelData);
+    gl::Error setData(const gl::Context *context,
+                      const gl::ImageIndex &index,
+                      ImageD3D *image,
+                      const gl::Box *destBox,
+                      GLenum type,
+                      const gl::PixelUnpackState &unpack,
+                      const uint8_t *pixelData) override;
 
   protected:
     int mTopLevel;
@@ -72,16 +81,20 @@
     TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
     ~TextureStorage9_2D() override;
 
-    gl::Error getSurfaceLevel(GLenum target,
+    gl::Error getSurfaceLevel(const gl::Context *context,
+                              GLenum target,
                               int level,
                               bool dirty,
                               IDirect3DSurface9 **outSurface) override;
-    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
-    gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) override;
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
+    gl::Error getBaseTexture(const gl::Context *context,
+                             IDirect3DBaseTexture9 **outTexture) override;
     gl::Error generateMipmap(const gl::Context *context,
                              const gl::ImageIndex &sourceIndex,
                              const gl::ImageIndex &destIndex) override;
-    gl::Error copyToStorage(TextureStorage *destStorage) override;
+    gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
 
   private:
     IDirect3DTexture9 *mTexture;
@@ -94,16 +107,20 @@
     TextureStorage9_EGLImage(Renderer9 *renderer, EGLImageD3D *image, RenderTarget9 *renderTarget9);
     ~TextureStorage9_EGLImage() override;
 
-    gl::Error getSurfaceLevel(GLenum target,
+    gl::Error getSurfaceLevel(const gl::Context *context,
+                              GLenum target,
                               int level,
                               bool dirty,
                               IDirect3DSurface9 **outSurface) override;
-    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
-    gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) override;
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
+    gl::Error getBaseTexture(const gl::Context *context,
+                             IDirect3DBaseTexture9 **outTexture) override;
     gl::Error generateMipmap(const gl::Context *context,
                              const gl::ImageIndex &sourceIndex,
                              const gl::ImageIndex &destIndex) override;
-    gl::Error copyToStorage(TextureStorage *destStorage) override;
+    gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
 
   private:
     EGLImageD3D *mImage;
@@ -115,16 +132,20 @@
     TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
     virtual ~TextureStorage9_Cube();
 
-    gl::Error getSurfaceLevel(GLenum target,
+    gl::Error getSurfaceLevel(const gl::Context *context,
+                              GLenum target,
                               int level,
                               bool dirty,
                               IDirect3DSurface9 **outSurface) override;
-    gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
-    gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) override;
+    gl::Error getRenderTarget(const gl::Context *context,
+                              const gl::ImageIndex &index,
+                              RenderTargetD3D **outRT) override;
+    gl::Error getBaseTexture(const gl::Context *context,
+                             IDirect3DBaseTexture9 **outTexture) override;
     gl::Error generateMipmap(const gl::Context *context,
                              const gl::ImageIndex &sourceIndex,
                              const gl::ImageIndex &destIndex) override;
-    gl::Error copyToStorage(TextureStorage *destStorage) override;
+    gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
 
   private:
     static const size_t CUBE_FACE_COUNT = 6;
diff --git a/src/libANGLE/renderer/gl/BlitGL.cpp b/src/libANGLE/renderer/gl/BlitGL.cpp
index ff35b2c..a97c9cf 100644
--- a/src/libANGLE/renderer/gl/BlitGL.cpp
+++ b/src/libANGLE/renderer/gl/BlitGL.cpp
@@ -163,7 +163,8 @@
     }
 }
 
-gl::Error BlitGL::copyImageToLUMAWorkaroundTexture(GLuint texture,
+gl::Error BlitGL::copyImageToLUMAWorkaroundTexture(const gl::Context *context,
+                                                   GLuint texture,
                                                    GLenum textureType,
                                                    GLenum target,
                                                    GLenum lumaFormat,
@@ -180,14 +181,15 @@
     gl::PixelUnpackState unpack;
     mStateManager->setPixelUnpackState(unpack);
     mFunctions->texImage2D(target, static_cast<GLint>(level), internalFormat, sourceArea.width,
-                           sourceArea.height, 0, format, source->getImplementationColorReadType(),
-                           nullptr);
+                           sourceArea.height, 0, format,
+                           source->getImplementationColorReadType(context), nullptr);
 
-    return copySubImageToLUMAWorkaroundTexture(texture, textureType, target, lumaFormat, level,
-                                               gl::Offset(0, 0, 0), sourceArea, source);
+    return copySubImageToLUMAWorkaroundTexture(context, texture, textureType, target, lumaFormat,
+                                               level, gl::Offset(0, 0, 0), sourceArea, source);
 }
 
-gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture,
+gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(const gl::Context *context,
+                                                      GLuint texture,
                                                       GLenum textureType,
                                                       GLenum target,
                                                       GLenum lumaFormat,
@@ -203,8 +205,8 @@
     mStateManager->bindFramebuffer(GL_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
 
     nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat(
-        mFunctions, mWorkarounds, source->getImplementationColorReadFormat(),
-        source->getImplementationColorReadType());
+        mFunctions, mWorkarounds, source->getImplementationColorReadFormat(context),
+        source->getImplementationColorReadType(context));
 
     mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
     mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.x,
@@ -224,7 +226,7 @@
     mFunctions->texImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.width,
                            sourceArea.height, 0,
                            gl::GetUnsizedFormat(copyTexImageFormat.internalFormat),
-                           source->getImplementationColorReadType(), nullptr);
+                           source->getImplementationColorReadType(context), nullptr);
 
     mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
     mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
@@ -426,7 +428,8 @@
     return gl::NoError();
 }
 
-gl::Error BlitGL::copySubTexture(TextureGL *source,
+gl::Error BlitGL::copySubTexture(const gl::Context *context,
+                                 TextureGL *source,
                                  size_t sourceLevel,
                                  TextureGL *dest,
                                  GLenum destTarget,
@@ -466,7 +469,7 @@
     }
     source->setMinFilter(GL_NEAREST);
     source->setMagFilter(GL_NEAREST);
-    source->setBaseLevel(static_cast<GLuint>(sourceLevel));
+    source->setBaseLevel(context, static_cast<GLuint>(sourceLevel));
 
     // Render to the destination texture, sampling from the source texture
     ScopedGLState scopedState(
diff --git a/src/libANGLE/renderer/gl/BlitGL.h b/src/libANGLE/renderer/gl/BlitGL.h
index aace372..0a49d05 100644
--- a/src/libANGLE/renderer/gl/BlitGL.h
+++ b/src/libANGLE/renderer/gl/BlitGL.h
@@ -36,7 +36,8 @@
            StateManagerGL *stateManager);
     ~BlitGL();
 
-    gl::Error copyImageToLUMAWorkaroundTexture(GLuint texture,
+    gl::Error copyImageToLUMAWorkaroundTexture(const gl::Context *context,
+                                               GLuint texture,
                                                GLenum textureType,
                                                GLenum target,
                                                GLenum lumaFormat,
@@ -45,7 +46,8 @@
                                                GLenum internalFormat,
                                                const gl::Framebuffer *source);
 
-    gl::Error copySubImageToLUMAWorkaroundTexture(GLuint texture,
+    gl::Error copySubImageToLUMAWorkaroundTexture(const gl::Context *context,
+                                                  GLuint texture,
                                                   GLenum textureType,
                                                   GLenum target,
                                                   GLenum lumaFormat,
@@ -60,7 +62,8 @@
                                         const gl::Rectangle &destArea,
                                         GLenum filter);
 
-    gl::Error copySubTexture(TextureGL *source,
+    gl::Error copySubTexture(const gl::Context *context,
+                             TextureGL *source,
                              size_t sourceLevel,
                              TextureGL *dest,
                              GLenum destTarget,
diff --git a/src/libANGLE/renderer/gl/ContextGL.cpp b/src/libANGLE/renderer/gl/ContextGL.cpp
index 08032ed..3f0fc9d 100644
--- a/src/libANGLE/renderer/gl/ContextGL.cpp
+++ b/src/libANGLE/renderer/gl/ContextGL.cpp
@@ -153,7 +153,7 @@
 
 gl::Error ContextGL::drawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count)
 {
-    return mRenderer->drawArrays(mState, mode, first, count);
+    return mRenderer->drawArrays(context, mode, first, count);
 }
 
 gl::Error ContextGL::drawArraysInstanced(const gl::Context *context,
@@ -162,7 +162,7 @@
                                          GLsizei count,
                                          GLsizei instanceCount)
 {
-    return mRenderer->drawArraysInstanced(mState, mode, first, count, instanceCount);
+    return mRenderer->drawArraysInstanced(context, mode, first, count, instanceCount);
 }
 
 gl::Error ContextGL::drawElements(const gl::Context *context,
@@ -172,7 +172,7 @@
                                   const void *indices,
                                   const gl::IndexRange &indexRange)
 {
-    return mRenderer->drawElements(mState, mode, count, type, indices, indexRange);
+    return mRenderer->drawElements(context, mode, count, type, indices, indexRange);
 }
 
 gl::Error ContextGL::drawElementsInstanced(const gl::Context *context,
@@ -183,7 +183,7 @@
                                            GLsizei instances,
                                            const gl::IndexRange &indexRange)
 {
-    return mRenderer->drawElementsInstanced(mState, mode, count, type, indices, instances,
+    return mRenderer->drawElementsInstanced(context, mode, count, type, indices, instances,
                                             indexRange);
 }
 
@@ -196,14 +196,15 @@
                                        const void *indices,
                                        const gl::IndexRange &indexRange)
 {
-    return mRenderer->drawRangeElements(mState, mode, start, end, count, type, indices, indexRange);
+    return mRenderer->drawRangeElements(context, mode, start, end, count, type, indices,
+                                        indexRange);
 }
 
 gl::Error ContextGL::drawArraysIndirect(const gl::Context *context,
                                         GLenum mode,
                                         const void *indirect)
 {
-    return mRenderer->drawArraysIndirect(mState, mode, indirect);
+    return mRenderer->drawArraysIndirect(context, mode, indirect);
 }
 
 gl::Error ContextGL::drawElementsIndirect(const gl::Context *context,
@@ -211,7 +212,7 @@
                                           GLenum type,
                                           const void *indirect)
 {
-    return mRenderer->drawElementsIndirect(mState, mode, type, indirect);
+    return mRenderer->drawElementsIndirect(context, mode, type, indirect);
 }
 
 void ContextGL::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
@@ -340,7 +341,7 @@
 
 void ContextGL::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits)
 {
-    mRenderer->getStateManager()->syncState(mState, dirtyBits);
+    mRenderer->getStateManager()->syncState(context, dirtyBits);
 }
 
 GLint ContextGL::getGPUDisjoint()
@@ -353,10 +354,10 @@
     return mRenderer->getTimestamp();
 }
 
-void ContextGL::onMakeCurrent(const gl::ContextState &data)
+void ContextGL::onMakeCurrent(const gl::Context *context)
 {
     // Queries need to be paused/resumed on context switches
-    mRenderer->getStateManager()->onMakeCurrent(data);
+    mRenderer->getStateManager()->onMakeCurrent(context);
 }
 
 const gl::Caps &ContextGL::getNativeCaps() const
@@ -399,7 +400,7 @@
                                      GLuint numGroupsY,
                                      GLuint numGroupsZ)
 {
-    return mRenderer->dispatchCompute(mState, numGroupsX, numGroupsY, numGroupsZ);
+    return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ);
 }
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/gl/ContextGL.h b/src/libANGLE/renderer/gl/ContextGL.h
index f0c67ac..3650ec1 100644
--- a/src/libANGLE/renderer/gl/ContextGL.h
+++ b/src/libANGLE/renderer/gl/ContextGL.h
@@ -175,7 +175,7 @@
     GLint64 getTimestamp() override;
 
     // Context switching
-    void onMakeCurrent(const gl::ContextState &data) override;
+    void onMakeCurrent(const gl::Context *context) override;
 
     // Caps queries
     const gl::Caps &getNativeCaps() const override;
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/libANGLE/renderer/gl/FramebufferGL.cpp
index e9e0e15..81211b1 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -132,13 +132,13 @@
     }
 }
 
-Error FramebufferGL::discard(size_t count, const GLenum *attachments)
+Error FramebufferGL::discard(const gl::Context *context, size_t count, const GLenum *attachments)
 {
     // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
-    return invalidate(count, attachments);
+    return invalidate(context, count, attachments);
 }
 
-Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
+Error FramebufferGL::invalidate(const gl::Context *context, size_t count, const GLenum *attachments)
 {
     const GLenum *finalAttachmentsPtr = attachments;
 
@@ -165,7 +165,8 @@
     return gl::NoError();
 }
 
-Error FramebufferGL::invalidateSub(size_t count,
+Error FramebufferGL::invalidateSub(const gl::Context *context,
+                                   size_t count,
                                    const GLenum *attachments,
                                    const gl::Rectangle &area)
 {
@@ -249,14 +250,14 @@
     return gl::NoError();
 }
 
-GLenum FramebufferGL::getImplementationColorReadFormat() const
+GLenum FramebufferGL::getImplementationColorReadFormat(const gl::Context *context) const
 {
     const auto *readAttachment = mState.getReadAttachment();
     const Format &format       = readAttachment->getFormat();
     return format.info->getReadPixelsFormat();
 }
 
-GLenum FramebufferGL::getImplementationColorReadType() const
+GLenum FramebufferGL::getImplementationColorReadType(const gl::Context *context) const
 {
     const auto *readAttachment = mState.getReadAttachment();
     const Format &format       = readAttachment->getFormat();
@@ -284,7 +285,7 @@
     if (mWorkarounds.packOverlappingRowsSeparatelyPackBuffer && packState.pixelBuffer.get() &&
         packState.rowLength != 0 && packState.rowLength < area.width)
     {
-        return readPixelsRowByRowWorkaround(area, readFormat, readType, packState, pixels);
+        return readPixelsRowByRowWorkaround(context, area, readFormat, readType, packState, pixels);
     }
 
     if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
@@ -298,7 +299,8 @@
 
         if (apply)
         {
-            return readPixelsPaddingWorkaround(area, readFormat, readType, packState, pixels);
+            return readPixelsPaddingWorkaround(context, area, readFormat, readType, packState,
+                                               pixels);
         }
     }
 
@@ -369,7 +371,7 @@
     }
 
     // Enable FRAMEBUFFER_SRGB if needed
-    mStateManager->setFramebufferSRGBEnabledForFramebuffer(context->getContextState(), true, this);
+    mStateManager->setFramebufferSRGBEnabledForFramebuffer(context, true, this);
 
     GLenum blitMask = mask;
     if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
@@ -527,11 +529,11 @@
                 }
             }
 
-            mStateManager->setFramebufferSRGBEnabled(context->getContextState(), hasSRGBAttachment);
+            mStateManager->setFramebufferSRGBEnabled(context, hasSRGBAttachment);
         }
         else
         {
-            mStateManager->setFramebufferSRGBEnabled(context->getContextState(), !mIsDefault);
+            mStateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
         }
     }
 }
@@ -561,13 +563,13 @@
 
             if (attachment != nullptr)
             {
-                mStateManager->setFramebufferSRGBEnabled(context->getContextState(),
+                mStateManager->setFramebufferSRGBEnabled(context,
                                                          attachment->getColorEncoding() == GL_SRGB);
             }
         }
         else
         {
-            mStateManager->setFramebufferSRGBEnabled(context->getContextState(), !mIsDefault);
+            mStateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
         }
     }
 }
@@ -609,7 +611,8 @@
     return true;
 }
 
-gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area,
+gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Context *context,
+                                                      const gl::Rectangle &area,
                                                       GLenum format,
                                                       GLenum type,
                                                       const gl::PixelPackState &pack,
@@ -625,10 +628,10 @@
     ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
 
     gl::PixelPackState directPack;
-    directPack.pixelBuffer = pack.pixelBuffer;
+    directPack.pixelBuffer.set(context, pack.pixelBuffer.get());
     directPack.alignment   = 1;
     mStateManager->setPixelPackState(directPack);
-    directPack.pixelBuffer.set(nullptr);
+    directPack.pixelBuffer.set(context, nullptr);
 
     offset += skipBytes;
     for (GLint row = 0; row < area.height; ++row)
@@ -641,7 +644,8 @@
     return gl::NoError();
 }
 
-gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area,
+gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Context *context,
+                                                     const gl::Rectangle &area,
                                                      GLenum format,
                                                      GLenum type,
                                                      const gl::PixelPackState &pack,
@@ -662,10 +666,10 @@
 
     // Get the last row manually
     gl::PixelPackState directPack;
-    directPack.pixelBuffer = pack.pixelBuffer;
+    directPack.pixelBuffer.set(context, pack.pixelBuffer.get());
     directPack.alignment   = 1;
     mStateManager->setPixelPackState(directPack);
-    directPack.pixelBuffer.set(nullptr);
+    directPack.pixelBuffer.set(context, nullptr);
 
     intptr_t lastRowOffset =
         reinterpret_cast<intptr_t>(pixels) + skipBytes + (area.height - 1) * rowBytes;
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.h b/src/libANGLE/renderer/gl/FramebufferGL.h
index ed93ba1..ab7c5b7 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.h
+++ b/src/libANGLE/renderer/gl/FramebufferGL.h
@@ -39,9 +39,12 @@
                   StateManagerGL *stateManager);
     ~FramebufferGL() override;
 
-    gl::Error discard(size_t count, const GLenum *attachments) override;
-    gl::Error invalidate(size_t count, const GLenum *attachments) override;
-    gl::Error invalidateSub(size_t count,
+    gl::Error discard(const gl::Context *context, size_t count, const GLenum *attachments) override;
+    gl::Error invalidate(const gl::Context *context,
+                         size_t count,
+                         const GLenum *attachments) override;
+    gl::Error invalidateSub(const gl::Context *context,
+                            size_t count,
                             const GLenum *attachments,
                             const gl::Rectangle &area) override;
 
@@ -64,8 +67,8 @@
                             GLfloat depth,
                             GLint stencil) override;
 
-    GLenum getImplementationColorReadFormat() const override;
-    GLenum getImplementationColorReadType() const override;
+    GLenum getImplementationColorReadFormat(const gl::Context *context) const override;
+    GLenum getImplementationColorReadType(const gl::Context *context) const override;
     gl::Error readPixels(const gl::Context *context,
                          const gl::Rectangle &area,
                          GLenum format,
@@ -99,13 +102,15 @@
         const GLenum *attachments,
         std::vector<GLenum> *modifiedAttachments) const;
 
-    gl::Error readPixelsRowByRowWorkaround(const gl::Rectangle &area,
+    gl::Error readPixelsRowByRowWorkaround(const gl::Context *context,
+                                           const gl::Rectangle &area,
                                            GLenum format,
                                            GLenum type,
                                            const gl::PixelPackState &pack,
                                            void *pixels) const;
 
-    gl::Error readPixelsPaddingWorkaround(const gl::Rectangle &area,
+    gl::Error readPixelsPaddingWorkaround(const gl::Context *context,
+                                          const gl::Rectangle &area,
                                           GLenum format,
                                           GLenum type,
                                           const gl::PixelPackState &pack,
diff --git a/src/libANGLE/renderer/gl/RendererGL.cpp b/src/libANGLE/renderer/gl/RendererGL.cpp
index 85d84cd..c024483 100644
--- a/src/libANGLE/renderer/gl/RendererGL.cpp
+++ b/src/libANGLE/renderer/gl/RendererGL.cpp
@@ -250,12 +250,12 @@
     return gl::NoError();
 }
 
-gl::Error RendererGL::drawArrays(const gl::ContextState &data,
+gl::Error RendererGL::drawArrays(const gl::Context *context,
                                  GLenum mode,
                                  GLint first,
                                  GLsizei count)
 {
-    ANGLE_TRY(mStateManager->setDrawArraysState(data, first, count, 0));
+    ANGLE_TRY(mStateManager->setDrawArraysState(context, first, count, 0));
 
     if (!mSkipDrawCalls)
     {
@@ -265,13 +265,13 @@
     return gl::NoError();
 }
 
-gl::Error RendererGL::drawArraysInstanced(const gl::ContextState &data,
+gl::Error RendererGL::drawArraysInstanced(const gl::Context *context,
                                           GLenum mode,
                                           GLint first,
                                           GLsizei count,
                                           GLsizei instanceCount)
 {
-    ANGLE_TRY(mStateManager->setDrawArraysState(data, first, count, instanceCount));
+    ANGLE_TRY(mStateManager->setDrawArraysState(context, first, count, instanceCount));
 
     if (!mSkipDrawCalls)
     {
@@ -281,7 +281,7 @@
     return gl::NoError();
 }
 
-gl::Error RendererGL::drawElements(const gl::ContextState &data,
+gl::Error RendererGL::drawElements(const gl::Context *context,
                                    GLenum mode,
                                    GLsizei count,
                                    GLenum type,
@@ -289,7 +289,7 @@
                                    const gl::IndexRange &indexRange)
 {
     const void *drawIndexPtr = nullptr;
-    ANGLE_TRY(mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPtr));
+    ANGLE_TRY(mStateManager->setDrawElementsState(context, count, type, indices, 0, &drawIndexPtr));
 
     if (!mSkipDrawCalls)
     {
@@ -299,7 +299,7 @@
     return gl::NoError();
 }
 
-gl::Error RendererGL::drawElementsInstanced(const gl::ContextState &data,
+gl::Error RendererGL::drawElementsInstanced(const gl::Context *context,
                                             GLenum mode,
                                             GLsizei count,
                                             GLenum type,
@@ -308,7 +308,7 @@
                                             const gl::IndexRange &indexRange)
 {
     const void *drawIndexPointer = nullptr;
-    ANGLE_TRY(mStateManager->setDrawElementsState(data, count, type, indices, instances,
+    ANGLE_TRY(mStateManager->setDrawElementsState(context, count, type, indices, instances,
                                                   &drawIndexPointer));
 
     if (!mSkipDrawCalls)
@@ -319,7 +319,7 @@
     return gl::NoError();
 }
 
-gl::Error RendererGL::drawRangeElements(const gl::ContextState &data,
+gl::Error RendererGL::drawRangeElements(const gl::Context *context,
                                         GLenum mode,
                                         GLuint start,
                                         GLuint end,
@@ -330,7 +330,7 @@
 {
     const void *drawIndexPointer = nullptr;
     ANGLE_TRY(
-        mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPointer));
+        mStateManager->setDrawElementsState(context, count, type, indices, 0, &drawIndexPointer));
 
     if (!mSkipDrawCalls)
     {
@@ -340,11 +340,11 @@
     return gl::NoError();
 }
 
-gl::Error RendererGL::drawArraysIndirect(const gl::ContextState &data,
+gl::Error RendererGL::drawArraysIndirect(const gl::Context *context,
                                          GLenum mode,
                                          const void *indirect)
 {
-    ANGLE_TRY(mStateManager->setDrawIndirectState(data, GL_NONE));
+    ANGLE_TRY(mStateManager->setDrawIndirectState(context, GL_NONE));
 
     if (!mSkipDrawCalls)
     {
@@ -353,12 +353,12 @@
     return gl::NoError();
 }
 
-gl::Error RendererGL::drawElementsIndirect(const gl::ContextState &data,
+gl::Error RendererGL::drawElementsIndirect(const gl::Context *context,
                                            GLenum mode,
                                            GLenum type,
                                            const void *indirect)
 {
-    ANGLE_TRY(mStateManager->setDrawIndirectState(data, type));
+    ANGLE_TRY(mStateManager->setDrawIndirectState(context, type));
 
     if (!mSkipDrawCalls)
     {
@@ -655,12 +655,12 @@
     return mNativeLimitations;
 }
 
-gl::Error RendererGL::dispatchCompute(const gl::ContextState &data,
+gl::Error RendererGL::dispatchCompute(const gl::Context *context,
                                       GLuint numGroupsX,
                                       GLuint numGroupsY,
                                       GLuint numGroupsZ)
 {
-    ANGLE_TRY(mStateManager->setDispatchComputeState(data));
+    ANGLE_TRY(mStateManager->setDispatchComputeState(context));
     mFunctions->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
     return gl::NoError();
 }
diff --git a/src/libANGLE/renderer/gl/RendererGL.h b/src/libANGLE/renderer/gl/RendererGL.h
index 82539f7..5306b74 100644
--- a/src/libANGLE/renderer/gl/RendererGL.h
+++ b/src/libANGLE/renderer/gl/RendererGL.h
@@ -49,27 +49,27 @@
     gl::Error flush();
     gl::Error finish();
 
-    gl::Error drawArrays(const gl::ContextState &data, GLenum mode, GLint first, GLsizei count);
-    gl::Error drawArraysInstanced(const gl::ContextState &data,
+    gl::Error drawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count);
+    gl::Error drawArraysInstanced(const gl::Context *context,
                                   GLenum mode,
                                   GLint first,
                                   GLsizei count,
                                   GLsizei instanceCount);
 
-    gl::Error drawElements(const gl::ContextState &data,
+    gl::Error drawElements(const gl::Context *context,
                            GLenum mode,
                            GLsizei count,
                            GLenum type,
                            const void *indices,
                            const gl::IndexRange &indexRange);
-    gl::Error drawElementsInstanced(const gl::ContextState &data,
+    gl::Error drawElementsInstanced(const gl::Context *context,
                                     GLenum mode,
                                     GLsizei count,
                                     GLenum type,
                                     const void *indices,
                                     GLsizei instances,
                                     const gl::IndexRange &indexRange);
-    gl::Error drawRangeElements(const gl::ContextState &data,
+    gl::Error drawRangeElements(const gl::Context *context,
                                 GLenum mode,
                                 GLuint start,
                                 GLuint end,
@@ -77,8 +77,8 @@
                                 GLenum type,
                                 const void *indices,
                                 const gl::IndexRange &indexRange);
-    gl::Error drawArraysIndirect(const gl::ContextState &data, GLenum mode, const void *indirect);
-    gl::Error drawElementsIndirect(const gl::ContextState &data,
+    gl::Error drawArraysIndirect(const gl::Context *context, GLenum mode, const void *indirect);
+    gl::Error drawElementsIndirect(const gl::Context *context,
                                    GLenum mode,
                                    GLenum type,
                                    const void *indirect);
@@ -166,7 +166,7 @@
     const gl::Extensions &getNativeExtensions() const;
     const gl::Limitations &getNativeLimitations() const;
 
-    gl::Error dispatchCompute(const gl::ContextState &data,
+    gl::Error dispatchCompute(const gl::Context *context,
                               GLuint numGroupsX,
                               GLuint numGroupsY,
                               GLuint numGroupsZ);
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.cpp b/src/libANGLE/renderer/gl/StateManagerGL.cpp
index d4362aa..c253f40 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.cpp
+++ b/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -14,7 +14,7 @@
 #include "common/bitset_utils.h"
 #include "common/mathutil.h"
 #include "common/matrix_utils.h"
-#include "libANGLE/ContextState.h"
+#include "libANGLE/Context.h"
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/Query.h"
 #include "libANGLE/TransformFeedback.h"
@@ -612,47 +612,43 @@
     mCurrentQueries.erase(query);
 }
 
-gl::Error StateManagerGL::setDrawArraysState(const gl::ContextState &data,
+gl::Error StateManagerGL::setDrawArraysState(const gl::Context *context,
                                              GLint first,
                                              GLsizei count,
                                              GLsizei instanceCount)
 {
-    const gl::State &state = data.getState();
+    const gl::State &glState = context->getGLState();
 
-    const gl::Program *program = state.getProgram();
+    const gl::Program *program = glState.getProgram();
 
-    const gl::VertexArray *vao = state.getVertexArray();
+    const gl::VertexArray *vao = glState.getVertexArray();
     const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
 
-    gl::Error error = vaoGL->syncDrawArraysState(program->getActiveAttribLocationsMask(), first,
-                                                 count, instanceCount);
-    if (error.isError())
-    {
-        return error;
-    }
+    ANGLE_TRY(vaoGL->syncDrawArraysState(context, program->getActiveAttribLocationsMask(), first,
+                                         count, instanceCount));
 
     bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
 
-    return setGenericDrawState(data);
+    return setGenericDrawState(context);
 }
 
-gl::Error StateManagerGL::setDrawElementsState(const gl::ContextState &data,
+gl::Error StateManagerGL::setDrawElementsState(const gl::Context *context,
                                                GLsizei count,
                                                GLenum type,
                                                const void *indices,
                                                GLsizei instanceCount,
                                                const void **outIndices)
 {
-    const gl::State &state = data.getState();
+    const gl::State &glState = context->getGLState();
 
-    const gl::Program *program = state.getProgram();
+    const gl::Program *program = glState.getProgram();
 
-    const gl::VertexArray *vao = state.getVertexArray();
+    const gl::VertexArray *vao = glState.getVertexArray();
     const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
 
-    gl::Error error =
-        vaoGL->syncDrawElementsState(program->getActiveAttribLocationsMask(), count, type, indices,
-                                     instanceCount, state.isPrimitiveRestartEnabled(), outIndices);
+    gl::Error error = vaoGL->syncDrawElementsState(context, program->getActiveAttribLocationsMask(),
+                                                   count, type, indices, instanceCount,
+                                                   glState.isPrimitiveRestartEnabled(), outIndices);
     if (error.isError())
     {
         return error;
@@ -660,33 +656,33 @@
 
     bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
 
-    return setGenericDrawState(data);
+    return setGenericDrawState(context);
 }
 
-gl::Error StateManagerGL::setDrawIndirectState(const gl::ContextState &data, GLenum type)
+gl::Error StateManagerGL::setDrawIndirectState(const gl::Context *context, GLenum type)
 {
-    const gl::State &state = data.getState();
+    const gl::State &glState = context->getGLState();
 
-    const gl::VertexArray *vao = state.getVertexArray();
+    const gl::VertexArray *vao = glState.getVertexArray();
     const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
 
     if (type != GL_NONE)
     {
-        ANGLE_TRY(vaoGL->syncElementArrayState());
+        ANGLE_TRY(vaoGL->syncElementArrayState(context));
     }
     bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
 
-    gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
+    gl::Buffer *drawIndirectBuffer = glState.getDrawIndirectBuffer();
     ASSERT(drawIndirectBuffer);
     const BufferGL *bufferGL = GetImplAs<BufferGL>(drawIndirectBuffer);
     bindBuffer(GL_DRAW_INDIRECT_BUFFER, bufferGL->getBufferID());
 
-    return setGenericDrawState(data);
+    return setGenericDrawState(context);
 }
 
-gl::Error StateManagerGL::setDispatchComputeState(const gl::ContextState &data)
+gl::Error StateManagerGL::setDispatchComputeState(const gl::Context *context)
 {
-    setGenericShaderState(data);
+    setGenericShaderState(context);
     return gl::NoError();
 }
 
@@ -736,23 +732,24 @@
     }
 }
 
-gl::Error StateManagerGL::onMakeCurrent(const gl::ContextState &data)
+gl::Error StateManagerGL::onMakeCurrent(const gl::Context *context)
 {
-    const gl::State &state = data.getState();
+    const gl::State &glState = context->getGLState();
 
     // If the context has changed, pause the previous context's queries
-    if (data.getContextID() != mPrevDrawContext)
+    auto contextID = context->getContextState().getContextID();
+    if (contextID != mPrevDrawContext)
     {
         pauseAllQueries();
     }
     mCurrentQueries.clear();
     mPrevDrawTransformFeedback = nullptr;
-    mPrevDrawContext           = data.getContextID();
+    mPrevDrawContext           = contextID;
 
     // Set the current query state
     for (GLenum queryType : QueryTypes)
     {
-        gl::Query *query = state.getActiveQuery(queryType);
+        gl::Query *query = glState.getActiveQuery(queryType);
         if (query != nullptr)
         {
             QueryGL *queryGL = GetImplAs<QueryGL>(query);
@@ -764,17 +761,17 @@
 
     // Seamless cubemaps are required for ES3 and higher contexts. It should be the cheapest to set
     // this state here since MakeCurrent is expected to be called less frequently than draw calls.
-    setTextureCubemapSeamlessEnabled(data.getClientMajorVersion() >= 3);
+    setTextureCubemapSeamlessEnabled(context->getClientMajorVersion() >= 3);
 
     return gl::NoError();
 }
 
-void StateManagerGL::setGenericShaderState(const gl::ContextState &data)
+void StateManagerGL::setGenericShaderState(const gl::Context *context)
 {
-    const gl::State &state = data.getState();
+    const gl::State &glState = context->getGLState();
 
     // Sync the current program state
-    const gl::Program *program = state.getProgram();
+    const gl::Program *program = glState.getProgram();
     const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
     useProgram(programGL->getProgramID());
 
@@ -782,7 +779,7 @@
          uniformBlockIndex++)
     {
         GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
-        const auto &uniformBuffer = state.getIndexedUniformBuffer(binding);
+        const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding);
 
         if (uniformBuffer.get() != nullptr)
         {
@@ -805,14 +802,14 @@
         GLenum textureType = samplerUniform.textureType;
         for (GLuint textureUnitIndex : samplerUniform.boundTextureUnits)
         {
-            gl::Texture *texture       = state.getSamplerTexture(textureUnitIndex, textureType);
-            const gl::Sampler *sampler = state.getSampler(textureUnitIndex);
+            gl::Texture *texture       = glState.getSamplerTexture(textureUnitIndex, textureType);
+            const gl::Sampler *sampler = glState.getSampler(textureUnitIndex);
 
             const gl::SamplerState &samplerState =
                 sampler ? sampler->getSamplerState() : texture->getSamplerState();
 
-            if (texture != nullptr &&
-                texture->getTextureState().isSamplerComplete(samplerState, data))
+            if (texture != nullptr && texture->getTextureState().isSamplerComplete(
+                                          samplerState, context->getContextState()))
             {
                 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
 
@@ -850,18 +847,18 @@
     }
 }
 
-gl::Error StateManagerGL::setGenericDrawState(const gl::ContextState &data)
+gl::Error StateManagerGL::setGenericDrawState(const gl::Context *context)
 {
-    setGenericShaderState(data);
+    setGenericShaderState(context);
 
-    const gl::State &state = data.getState();
+    const gl::State &glState = context->getGLState();
 
-    gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
+    gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
     FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
     bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferGL->getFramebufferID());
 
     // Set the current transform feedback state
-    gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
+    gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
     if (transformFeedback)
     {
         TransformFeedbackGL *transformFeedbackGL =
@@ -878,9 +875,9 @@
         mPrevDrawTransformFeedback = nullptr;
     }
 
-    if (data.getExtensions().webglCompatibility)
+    if (context->getExtensions().webglCompatibility)
     {
-        auto activeOutputs = state.getProgram()->getState().getActiveOutputVariables();
+        auto activeOutputs = glState.getProgram()->getState().getActiveOutputVariables();
         framebufferGL->maskOutInactiveOutputDrawBuffers(activeOutputs);
     }
 
@@ -1407,10 +1404,9 @@
     }
 }
 
-void StateManagerGL::syncState(const gl::ContextState &data,
-                               const gl::State::DirtyBits &glDirtyBits)
+void StateManagerGL::syncState(const gl::Context *context, const gl::State::DirtyBits &glDirtyBits)
 {
-    const gl::State &state = data.getState();
+    const gl::State &state = context->getGLState();
 
     // The the current framebuffer binding sometimes requires resetting the srgb blending
     if (glDirtyBits[gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING] &&
@@ -1664,7 +1660,7 @@
                 break;
             case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB:
                 setFramebufferSRGBEnabledForFramebuffer(
-                    data, state.getFramebufferSRGB(),
+                    context, state.getFramebufferSRGB(),
                     GetImplAs<FramebufferGL>(state.getDrawFramebuffer()));
                 break;
             default:
@@ -1683,9 +1679,9 @@
     }
 }
 
-void StateManagerGL::setFramebufferSRGBEnabled(const gl::ContextState &data, bool enabled)
+void StateManagerGL::setFramebufferSRGBEnabled(const gl::Context *context, bool enabled)
 {
-    if (!data.getExtensions().sRGBWriteControl)
+    if (!context->getExtensions().sRGBWriteControl)
     {
         return;
     }
@@ -1705,7 +1701,7 @@
     }
 }
 
-void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(const gl::ContextState &data,
+void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context,
                                                              bool enabled,
                                                              const FramebufferGL *framebuffer)
 {
@@ -1716,11 +1712,11 @@
         // When SRGB blending is enabled, only SRGB capable formats will use it but the default
         // framebuffer will always use it if it is enabled.
         // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
-        setFramebufferSRGBEnabled(data, false);
+        setFramebufferSRGBEnabled(context, false);
     }
     else
     {
-        setFramebufferSRGBEnabled(data, enabled);
+        setFramebufferSRGBEnabled(context, enabled);
     }
 }
 
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.h b/src/libANGLE/renderer/gl/StateManagerGL.h
index 43dab84..528c722 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.h
+++ b/src/libANGLE/renderer/gl/StateManagerGL.h
@@ -123,8 +123,8 @@
                            GLint skipPixels,
                            GLuint packBuffer);
 
-    void setFramebufferSRGBEnabled(const gl::ContextState &data, bool enabled);
-    void setFramebufferSRGBEnabledForFramebuffer(const gl::ContextState &data,
+    void setFramebufferSRGBEnabled(const gl::Context *context, bool enabled);
+    void setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context,
                                                  bool enabled,
                                                  const FramebufferGL *framebuffer);
 
@@ -141,35 +141,35 @@
 
     void onDeleteQueryObject(QueryGL *query);
 
-    gl::Error setDrawArraysState(const gl::ContextState &data,
+    gl::Error setDrawArraysState(const gl::Context *context,
                                  GLint first,
                                  GLsizei count,
                                  GLsizei instanceCount);
-    gl::Error setDrawElementsState(const gl::ContextState &data,
+    gl::Error setDrawElementsState(const gl::Context *context,
                                    GLsizei count,
                                    GLenum type,
                                    const void *indices,
                                    GLsizei instanceCount,
                                    const void **outIndices);
-    gl::Error setDrawIndirectState(const gl::ContextState &data, GLenum type);
+    gl::Error setDrawIndirectState(const gl::Context *context, GLenum type);
 
-    gl::Error setDispatchComputeState(const gl::ContextState &data);
+    gl::Error setDispatchComputeState(const gl::Context *context);
 
     void pauseTransformFeedback();
     void pauseAllQueries();
     void pauseQuery(GLenum type);
     void resumeAllQueries();
     void resumeQuery(GLenum type);
-    gl::Error onMakeCurrent(const gl::ContextState &data);
+    gl::Error onMakeCurrent(const gl::Context *context);
 
-    void syncState(const gl::ContextState &data, const gl::State::DirtyBits &glDirtyBits);
+    void syncState(const gl::Context *context, const gl::State::DirtyBits &glDirtyBits);
 
   private:
     // Set state that's common among draw commands and compute invocations.
-    void setGenericShaderState(const gl::ContextState &data);
+    void setGenericShaderState(const gl::Context *context);
 
     // Set state that's common among draw commands.
-    gl::Error setGenericDrawState(const gl::ContextState &data);
+    gl::Error setGenericDrawState(const gl::Context *context);
 
     void setTextureCubemapSeamlessEnabled(bool enabled);
 
diff --git a/src/libANGLE/renderer/gl/TextureGL.cpp b/src/libANGLE/renderer/gl/TextureGL.cpp
index e988892..a4c1deb 100644
--- a/src/libANGLE/renderer/gl/TextureGL.cpp
+++ b/src/libANGLE/renderer/gl/TextureGL.cpp
@@ -180,7 +180,8 @@
         }
 
         gl::Box area(0, 0, 0, size.width, size.height, size.depth);
-        return setSubImageRowByRowWorkaround(target, level, area, format, type, unpack, pixels);
+        return setSubImageRowByRowWorkaround(context, target, level, area, format, type, unpack,
+                                             pixels);
     }
 
     if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion)
@@ -202,7 +203,8 @@
             }
 
             gl::Box area(0, 0, 0, size.width, size.height, size.depth);
-            return setSubImagePaddingWorkaround(target, level, area, format, type, unpack, pixels);
+            return setSubImagePaddingWorkaround(context, target, level, area, format, type, unpack,
+                                                pixels);
         }
     }
 
@@ -280,7 +282,8 @@
     if (mWorkarounds.unpackOverlappingRowsSeparatelyUnpackBuffer && unpack.pixelBuffer.get() &&
         unpack.rowLength != 0 && unpack.rowLength < area.width)
     {
-        return setSubImageRowByRowWorkaround(target, level, area, format, type, unpack, pixels);
+        return setSubImageRowByRowWorkaround(context, target, level, area, format, type, unpack,
+                                             pixels);
     }
 
     if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion)
@@ -296,7 +299,8 @@
         // by uploading the last row (and last level if 3D) separately.
         if (apply)
         {
-            return setSubImagePaddingWorkaround(target, level, area, format, type, unpack, pixels);
+            return setSubImagePaddingWorkaround(context, target, level, area, format, type, unpack,
+                                                pixels);
         }
     }
 
@@ -318,7 +322,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureGL::setSubImageRowByRowWorkaround(GLenum target,
+gl::Error TextureGL::setSubImageRowByRowWorkaround(const gl::Context *context,
+                                                   GLenum target,
                                                    size_t level,
                                                    const gl::Box &area,
                                                    GLenum format,
@@ -327,10 +332,10 @@
                                                    const uint8_t *pixels)
 {
     gl::PixelUnpackState directUnpack;
-    directUnpack.pixelBuffer = unpack.pixelBuffer;
+    directUnpack.pixelBuffer.set(context, unpack.pixelBuffer.get());
     directUnpack.alignment   = 1;
     mStateManager->setPixelUnpackState(directUnpack);
-    directUnpack.pixelBuffer.set(nullptr);
+    directUnpack.pixelBuffer.set(context, nullptr);
 
     const gl::InternalFormat &glFormat   = gl::GetInternalFormatInfo(format, type);
     GLuint rowBytes                      = 0;
@@ -374,7 +379,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureGL::setSubImagePaddingWorkaround(GLenum target,
+gl::Error TextureGL::setSubImagePaddingWorkaround(const gl::Context *context,
+                                                  GLenum target,
                                                   size_t level,
                                                   const gl::Box &area,
                                                   GLenum format,
@@ -397,7 +403,7 @@
     mStateManager->setPixelUnpackState(unpack);
 
     gl::PixelUnpackState directUnpack;
-    directUnpack.pixelBuffer = unpack.pixelBuffer;
+    directUnpack.pixelBuffer.set(context, unpack.pixelBuffer.get());
     directUnpack.alignment   = 1;
 
     if (useTexImage3D)
@@ -453,7 +459,7 @@
                                   lastRowPixels);
     }
 
-    directUnpack.pixelBuffer.set(nullptr);
+    directUnpack.pixelBuffer.set(context, nullptr);
 
     return gl::NoError();
 }
@@ -546,13 +552,13 @@
                                const gl::Framebuffer *source)
 {
     nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat(
-        mFunctions, mWorkarounds, internalFormat, source->getImplementationColorReadType());
+        mFunctions, mWorkarounds, internalFormat, source->getImplementationColorReadType(context));
 
     LevelInfoGL levelInfo = GetLevelInfo(internalFormat, copyTexImageFormat.internalFormat);
     if (levelInfo.lumaWorkaround.enabled)
     {
         gl::Error error = mBlitter->copyImageToLUMAWorkaroundTexture(
-            mTextureID, getTarget(), target, levelInfo.sourceFormat, level, sourceArea,
+            context, mTextureID, getTarget(), target, levelInfo.sourceFormat, level, sourceArea,
             copyTexImageFormat.internalFormat, source);
         if (error.isError())
         {
@@ -600,8 +606,8 @@
     if (levelInfo.lumaWorkaround.enabled)
     {
         gl::Error error = mBlitter->copySubImageToLUMAWorkaroundTexture(
-            mTextureID, getTarget(), target, levelInfo.sourceFormat, level, destOffset, sourceArea,
-            source);
+            context, mTextureID, getTarget(), target, levelInfo.sourceFormat, level, destOffset,
+            sourceArea, source);
         if (error.isError())
         {
             return error;
@@ -650,8 +656,8 @@
     reserveTexImageToBeFilled(target, level, internalFormat, sourceImageDesc.size,
                               gl::GetUnsizedFormat(internalFormat), type);
 
-    return copySubTextureHelper(target, level, gl::Offset(0, 0, 0), sourceLevel, sourceArea,
-                                internalFormat, unpackFlipY, unpackPremultiplyAlpha,
+    return copySubTextureHelper(context, target, level, gl::Offset(0, 0, 0), sourceLevel,
+                                sourceArea, internalFormat, unpackFlipY, unpackPremultiplyAlpha,
                                 unpackUnmultiplyAlpha, source);
 }
 
@@ -667,11 +673,13 @@
                                     const gl::Texture *source)
 {
     GLenum destFormat = mState.getImageDesc(target, level).format.info->format;
-    return copySubTextureHelper(target, level, destOffset, sourceLevel, sourceArea, destFormat,
-                                unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha, source);
+    return copySubTextureHelper(context, target, level, destOffset, sourceLevel, sourceArea,
+                                destFormat, unpackFlipY, unpackPremultiplyAlpha,
+                                unpackUnmultiplyAlpha, source);
 }
 
-gl::Error TextureGL::copySubTextureHelper(GLenum target,
+gl::Error TextureGL::copySubTextureHelper(const gl::Context *context,
+                                          GLenum target,
                                           size_t level,
                                           const gl::Offset &destOffset,
                                           size_t sourceLevel,
@@ -705,7 +713,7 @@
     }
 
     // We can't use copyTexSubImage, do a manual copy
-    return mBlitter->copySubTexture(sourceGL, sourceLevel, this, target, level,
+    return mBlitter->copySubTexture(context, sourceGL, sourceLevel, this, target, level,
                                     sourceImageDesc.size, sourceArea, destOffset,
                                     needsLumaWorkaround, sourceLevelInfo.sourceFormat, unpackFlipY,
                                     unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
@@ -899,7 +907,8 @@
     return gl::NoError();
 }
 
-gl::Error TextureGL::setImageExternal(GLenum target,
+gl::Error TextureGL::setImageExternal(const gl::Context *context,
+                                      GLenum target,
                                       egl::Stream *stream,
                                       const egl::Stream::GLTextureDescription &desc)
 {
@@ -921,7 +930,7 @@
     return gl::NoError();
 }
 
-void TextureGL::bindTexImage(egl::Surface *surface)
+gl::Error TextureGL::bindTexImage(const gl::Context *context, egl::Surface *surface)
 {
     ASSERT(getTarget() == GL_TEXTURE_2D);
 
@@ -929,9 +938,10 @@
     mStateManager->bindTexture(getTarget(), mTextureID);
 
     setLevelInfo(getTarget(), 0, 1, LevelInfoGL());
+    return gl::NoError();
 }
 
-void TextureGL::releaseTexImage()
+gl::Error TextureGL::releaseTexImage(const gl::Context *context)
 {
     // Not all Surface implementations reset the size of mip 0 when releasing, do it manually
     ASSERT(getTarget() == GL_TEXTURE_2D);
@@ -946,9 +956,10 @@
     {
         UNREACHABLE();
     }
+    return gl::NoError();
 }
 
-gl::Error TextureGL::setEGLImageTarget(GLenum target, egl::Image *image)
+gl::Error TextureGL::setEGLImageTarget(const gl::Context *context, GLenum target, egl::Image *image)
 {
     UNIMPLEMENTED();
     return gl::InternalError();
@@ -1070,7 +1081,7 @@
     return mLocalDirtyBits.any();
 }
 
-void TextureGL::setBaseLevel(GLuint baseLevel)
+gl::Error TextureGL::setBaseLevel(const gl::Context *context, GLuint baseLevel)
 {
     if (baseLevel != mAppliedBaseLevel)
     {
@@ -1080,6 +1091,7 @@
         mStateManager->bindTexture(getTarget(), mTextureID);
         mFunctions->texParameteri(getTarget(), GL_TEXTURE_BASE_LEVEL, baseLevel);
     }
+    return gl::NoError();
 }
 
 void TextureGL::setMinFilter(GLenum filter)
diff --git a/src/libANGLE/renderer/gl/TextureGL.h b/src/libANGLE/renderer/gl/TextureGL.h
index f3dc1a1..c3f3fdc 100644
--- a/src/libANGLE/renderer/gl/TextureGL.h
+++ b/src/libANGLE/renderer/gl/TextureGL.h
@@ -127,7 +127,8 @@
                              bool unpackPremultiplyAlpha,
                              bool unpackUnmultiplyAlpha,
                              const gl::Texture *source) override;
-    gl::Error copySubTextureHelper(GLenum target,
+    gl::Error copySubTextureHelper(const gl::Context *context,
+                                   GLenum target,
                                    size_t level,
                                    const gl::Offset &destOffset,
                                    size_t sourceLevel,
@@ -151,16 +152,19 @@
                                     const gl::Extents &size,
                                     GLboolean fixedSampleLocations) override;
 
-    gl::Error setImageExternal(GLenum target,
+    gl::Error setImageExternal(const gl::Context *context,
+                               GLenum target,
                                egl::Stream *stream,
                                const egl::Stream::GLTextureDescription &desc) override;
 
     gl::Error generateMipmap(const gl::Context *context) override;
 
-    void bindTexImage(egl::Surface *surface) override;
-    void releaseTexImage() override;
+    gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+    gl::Error releaseTexImage(const gl::Context *context) override;
 
-    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+    gl::Error setEGLImageTarget(const gl::Context *context,
+                                GLenum target,
+                                egl::Image *image) override;
 
     GLuint getTextureID() const;
     GLenum getTarget() const;
@@ -168,7 +172,7 @@
     void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
     bool hasAnyDirtyBit() const;
 
-    void setBaseLevel(GLuint baseLevel) override;
+    gl::Error setBaseLevel(const gl::Context *context, GLuint baseLevel) override;
 
     void setMinFilter(GLenum filter);
     void setMagFilter(GLenum filter);
@@ -190,7 +194,8 @@
                                    const gl::Extents &size,
                                    GLenum format,
                                    GLenum type);
-    gl::Error setSubImageRowByRowWorkaround(GLenum target,
+    gl::Error setSubImageRowByRowWorkaround(const gl::Context *context,
+                                            GLenum target,
                                             size_t level,
                                             const gl::Box &area,
                                             GLenum format,
@@ -198,7 +203,8 @@
                                             const gl::PixelUnpackState &unpack,
                                             const uint8_t *pixels);
 
-    gl::Error setSubImagePaddingWorkaround(GLenum target,
+    gl::Error setSubImagePaddingWorkaround(const gl::Context *context,
+                                           GLenum target,
                                            size_t level,
                                            const gl::Box &area,
                                            GLenum format,
diff --git a/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp b/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
index ae75a0f..33354f8 100644
--- a/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
+++ b/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
@@ -56,11 +56,12 @@
     // Do not resume directly, StateManagerGL will handle beginning and resuming transform feedback.
 }
 
-void TransformFeedbackGL::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
+void TransformFeedbackGL::bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding)
 {
 }
 
-void TransformFeedbackGL::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding)
+void TransformFeedbackGL::bindIndexedBuffer(size_t index,
+                                            const gl::OffsetBindingPointer<gl::Buffer> &binding)
 {
     // Directly bind buffer (not through the StateManager methods) because the buffer bindings are
     // tracked per transform feedback object
diff --git a/src/libANGLE/renderer/gl/TransformFeedbackGL.h b/src/libANGLE/renderer/gl/TransformFeedbackGL.h
index f84edc0..1a6375d 100644
--- a/src/libANGLE/renderer/gl/TransformFeedbackGL.h
+++ b/src/libANGLE/renderer/gl/TransformFeedbackGL.h
@@ -30,8 +30,9 @@
     void pause() override;
     void resume() override;
 
-    void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
-    void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+    void bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding) override;
+    void bindIndexedBuffer(size_t index,
+                           const gl::OffsetBindingPointer<gl::Buffer> &binding) override;
 
     GLuint getTransformFeedbackID() const;
 
diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/src/libANGLE/renderer/gl/VertexArrayGL.cpp
index 86252a7..afd1476 100644
--- a/src/libANGLE/renderer/gl/VertexArrayGL.cpp
+++ b/src/libANGLE/renderer/gl/VertexArrayGL.cpp
@@ -76,7 +76,7 @@
     }
 }
 
-VertexArrayGL::~VertexArrayGL()
+void VertexArrayGL::destroy(const gl::Context *context)
 {
     mStateManager->deleteVertexArray(mVertexArrayID);
     mVertexArrayID = 0;
@@ -89,23 +89,25 @@
     mStreamingArrayBufferSize = 0;
     mStreamingArrayBuffer     = 0;
 
-    mAppliedElementArrayBuffer.set(nullptr);
+    mAppliedElementArrayBuffer.set(context, nullptr);
     for (auto &binding : mAppliedBindings)
     {
-        binding.setBuffer(nullptr);
+        binding.setBuffer(context, nullptr);
     }
 }
 
-gl::Error VertexArrayGL::syncDrawArraysState(const gl::AttributesMask &activeAttributesMask,
+gl::Error VertexArrayGL::syncDrawArraysState(const gl::Context *context,
+                                             const gl::AttributesMask &activeAttributesMask,
                                              GLint first,
                                              GLsizei count,
                                              GLsizei instanceCount) const
 {
-    return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, instanceCount, false,
-                         nullptr);
+    return syncDrawState(context, activeAttributesMask, first, count, GL_NONE, nullptr,
+                         instanceCount, false, nullptr);
 }
 
-gl::Error VertexArrayGL::syncDrawElementsState(const gl::AttributesMask &activeAttributesMask,
+gl::Error VertexArrayGL::syncDrawElementsState(const gl::Context *context,
+                                               const gl::AttributesMask &activeAttributesMask,
                                                GLsizei count,
                                                GLenum type,
                                                const void *indices,
@@ -113,11 +115,11 @@
                                                bool primitiveRestartEnabled,
                                                const void **outIndices) const
 {
-    return syncDrawState(activeAttributesMask, 0, count, type, indices, instanceCount,
+    return syncDrawState(context, activeAttributesMask, 0, count, type, indices, instanceCount,
                          primitiveRestartEnabled, outIndices);
 }
 
-gl::Error VertexArrayGL::syncElementArrayState() const
+gl::Error VertexArrayGL::syncElementArrayState(const gl::Context *context) const
 {
     gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get();
     ASSERT(elementArrayBuffer);
@@ -125,13 +127,14 @@
     {
         const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
         mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID());
-        mAppliedElementArrayBuffer.set(elementArrayBuffer);
+        mAppliedElementArrayBuffer.set(context, elementArrayBuffer);
     }
 
     return gl::NoError();
 }
 
-gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask,
+gl::Error VertexArrayGL::syncDrawState(const gl::Context *context,
+                                       const gl::AttributesMask &activeAttributesMask,
                                        GLint first,
                                        GLsizei count,
                                        GLenum type,
@@ -151,12 +154,8 @@
     IndexRange indexRange;
     if (type != GL_NONE)
     {
-        Error error = syncIndexData(count, type, indices, primitiveRestartEnabled,
-                                    attributesNeedStreaming, &indexRange, outIndices);
-        if (error.isError())
-        {
-            return error;
-        }
+        ANGLE_TRY(syncIndexData(context, count, type, indices, primitiveRestartEnabled,
+                                attributesNeedStreaming, &indexRange, outIndices));
     }
     else
     {
@@ -167,17 +166,14 @@
 
     if (attributesNeedStreaming)
     {
-        Error error = streamAttributes(activeAttributesMask, instanceCount, indexRange);
-        if (error.isError())
-        {
-            return error;
-        }
+        ANGLE_TRY(streamAttributes(activeAttributesMask, instanceCount, indexRange));
     }
 
     return gl::NoError();
 }
 
-gl::Error VertexArrayGL::syncIndexData(GLsizei count,
+gl::Error VertexArrayGL::syncIndexData(const gl::Context *context,
+                                       GLsizei count,
                                        GLenum type,
                                        const void *indices,
                                        bool primitiveRestartEnabled,
@@ -196,7 +192,7 @@
         {
             const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
             mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID());
-            mAppliedElementArrayBuffer.set(elementArrayBuffer);
+            mAppliedElementArrayBuffer.set(context, elementArrayBuffer);
         }
 
         // Only compute the index range if the attributes also need to be streamed
@@ -234,7 +230,7 @@
         }
 
         mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mStreamingElementArrayBuffer);
-        mAppliedElementArrayBuffer.set(nullptr);
+        mAppliedElementArrayBuffer.set(context, nullptr);
 
         // Make sure the element array buffer is large enough
         const Type &indexTypeInfo          = GetTypeInfo(type);
@@ -447,7 +443,7 @@
     mAppliedAttributes[attribIndex].enabled = enabled;
 }
 
-void VertexArrayGL::updateAttribPointer(size_t attribIndex)
+void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attribIndex)
 {
     const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
 
@@ -477,7 +473,7 @@
         // Mark the applied binding is using a client memory pointer by setting its buffer to
         // nullptr so that if it doesn't use a client memory pointer later, there is no chance that
         // the caching will skip it.
-        mAppliedBindings[bindingIndex].setBuffer(nullptr);
+        mAppliedBindings[bindingIndex].setBuffer(context, nullptr);
         return;
     }
 
@@ -503,7 +499,7 @@
 
     mAppliedBindings[bindingIndex].setStride(binding.getStride());
     mAppliedBindings[bindingIndex].setOffset(binding.getOffset());
-    mAppliedBindings[bindingIndex].setBuffer(binding.getBuffer().get());
+    mAppliedBindings[bindingIndex].setBuffer(context, binding.getBuffer().get());
 }
 
 void VertexArrayGL::callVertexAttribPointer(GLuint attribIndex,
@@ -563,7 +559,7 @@
         else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_POINTER &&
                  dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER)
         {
-            updateAttribPointer(index);
+            updateAttribPointer(context, index);
         }
         else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_FORMAT &&
                  dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX_BUFFER)
diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.h b/src/libANGLE/renderer/gl/VertexArrayGL.h
index d7c5578..bb9104c 100644
--- a/src/libANGLE/renderer/gl/VertexArrayGL.h
+++ b/src/libANGLE/renderer/gl/VertexArrayGL.h
@@ -23,20 +23,22 @@
     VertexArrayGL(const gl::VertexArrayState &data,
                   const FunctionsGL *functions,
                   StateManagerGL *stateManager);
-    ~VertexArrayGL() override;
+    void destroy(const gl::Context *context) override;
 
-    gl::Error syncDrawArraysState(const gl::AttributesMask &activeAttributesMask,
+    gl::Error syncDrawArraysState(const gl::Context *context,
+                                  const gl::AttributesMask &activeAttributesMask,
                                   GLint first,
                                   GLsizei count,
                                   GLsizei instanceCount) const;
-    gl::Error syncDrawElementsState(const gl::AttributesMask &activeAttributesMask,
+    gl::Error syncDrawElementsState(const gl::Context *context,
+                                    const gl::AttributesMask &activeAttributesMask,
                                     GLsizei count,
                                     GLenum type,
                                     const void *indices,
                                     GLsizei instanceCount,
                                     bool primitiveRestartEnabled,
                                     const void **outIndices) const;
-    gl::Error syncElementArrayState() const;
+    gl::Error syncElementArrayState(const gl::Context *context) const;
 
     GLuint getVertexArrayID() const;
     GLuint getAppliedElementArrayBufferID() const;
@@ -45,7 +47,8 @@
                    const gl::VertexArray::DirtyBits &dirtyBits) override;
 
   private:
-    gl::Error syncDrawState(const gl::AttributesMask &activeAttributesMask,
+    gl::Error syncDrawState(const gl::Context *context,
+                            const gl::AttributesMask &activeAttributesMask,
                             GLint first,
                             GLsizei count,
                             GLenum type,
@@ -55,7 +58,8 @@
                             const void **outIndices) const;
 
     // Apply index data, only sets outIndexRange if attributesNeedStreaming is true
-    gl::Error syncIndexData(GLsizei count,
+    gl::Error syncIndexData(const gl::Context *context,
+                            GLsizei count,
                             GLenum type,
                             const void *indices,
                             bool primitiveRestartEnabled,
@@ -78,7 +82,7 @@
 
     void updateNeedsStreaming(size_t attribIndex);
     void updateAttribEnabled(size_t attribIndex);
-    void updateAttribPointer(size_t attribIndex);
+    void updateAttribPointer(const gl::Context *context, size_t attribIndex);
     void updateAttribDivisor(size_t attribIndex);
 
     void callVertexAttribPointer(GLuint attribIndex,
@@ -91,7 +95,7 @@
 
     GLuint mVertexArrayID;
 
-    mutable BindingPointer<gl::Buffer> mAppliedElementArrayBuffer;
+    mutable gl::BindingPointer<gl::Buffer> mAppliedElementArrayBuffer;
 
     mutable std::vector<gl::VertexAttribute> mAppliedAttributes;
     mutable std::vector<gl::VertexBinding> mAppliedBindings;
diff --git a/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp b/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
index 199d7eb..de5eef2 100644
--- a/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
+++ b/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
@@ -18,9 +18,9 @@
 #include "libANGLE/Context.h"
 #include "libANGLE/Display.h"
 #include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
 #include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h"
 #include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h"
-#include "libANGLE/renderer/gl/RendererGL.h"
 #include "libANGLE/renderer/gl/renderergl_utils.h"
 
 namespace rx
diff --git a/src/libANGLE/renderer/null/ContextNULL.cpp b/src/libANGLE/renderer/null/ContextNULL.cpp
index 8c375cb..14e6f6b 100644
--- a/src/libANGLE/renderer/null/ContextNULL.cpp
+++ b/src/libANGLE/renderer/null/ContextNULL.cpp
@@ -276,7 +276,7 @@
     return 0;
 }
 
-void ContextNULL::onMakeCurrent(const gl::ContextState &data)
+void ContextNULL::onMakeCurrent(const gl::Context *context)
 {
 }
 
diff --git a/src/libANGLE/renderer/null/ContextNULL.h b/src/libANGLE/renderer/null/ContextNULL.h
index 39bec0a..0fe79ed 100644
--- a/src/libANGLE/renderer/null/ContextNULL.h
+++ b/src/libANGLE/renderer/null/ContextNULL.h
@@ -148,7 +148,7 @@
     GLint64 getTimestamp() override;
 
     // Context switching
-    void onMakeCurrent(const gl::ContextState &data) override;
+    void onMakeCurrent(const gl::Context *context) override;
 
     // Native capabilities, unmodified by gl::Context.
     const gl::Caps &getNativeCaps() const override;
diff --git a/src/libANGLE/renderer/null/FramebufferNULL.cpp b/src/libANGLE/renderer/null/FramebufferNULL.cpp
index eb02b95..b64dd2a 100644
--- a/src/libANGLE/renderer/null/FramebufferNULL.cpp
+++ b/src/libANGLE/renderer/null/FramebufferNULL.cpp
@@ -24,17 +24,22 @@
 {
 }
 
-gl::Error FramebufferNULL::discard(size_t count, const GLenum *attachments)
+gl::Error FramebufferNULL::discard(const gl::Context *context,
+                                   size_t count,
+                                   const GLenum *attachments)
 {
     return gl::NoError();
 }
 
-gl::Error FramebufferNULL::invalidate(size_t count, const GLenum *attachments)
+gl::Error FramebufferNULL::invalidate(const gl::Context *context,
+                                      size_t count,
+                                      const GLenum *attachments)
 {
     return gl::NoError();
 }
 
-gl::Error FramebufferNULL::invalidateSub(size_t count,
+gl::Error FramebufferNULL::invalidateSub(const gl::Context *context,
+                                         size_t count,
                                          const GLenum *attachments,
                                          const gl::Rectangle &area)
 {
@@ -79,7 +84,7 @@
     return gl::NoError();
 }
 
-GLenum FramebufferNULL::getImplementationColorReadFormat() const
+GLenum FramebufferNULL::getImplementationColorReadFormat(const gl::Context *context) const
 {
     const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
     if (readAttachment == nullptr)
@@ -92,7 +97,7 @@
     return format.info->getReadPixelsFormat();
 }
 
-GLenum FramebufferNULL::getImplementationColorReadType() const
+GLenum FramebufferNULL::getImplementationColorReadType(const gl::Context *context) const
 {
     const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
     if (readAttachment == nullptr)
diff --git a/src/libANGLE/renderer/null/FramebufferNULL.h b/src/libANGLE/renderer/null/FramebufferNULL.h
index 9451487..f220104 100644
--- a/src/libANGLE/renderer/null/FramebufferNULL.h
+++ b/src/libANGLE/renderer/null/FramebufferNULL.h
@@ -21,9 +21,12 @@
     FramebufferNULL(const gl::FramebufferState &state);
     ~FramebufferNULL() override;
 
-    gl::Error discard(size_t count, const GLenum *attachments) override;
-    gl::Error invalidate(size_t count, const GLenum *attachments) override;
-    gl::Error invalidateSub(size_t count,
+    gl::Error discard(const gl::Context *context, size_t count, const GLenum *attachments) override;
+    gl::Error invalidate(const gl::Context *context,
+                         size_t count,
+                         const GLenum *attachments) override;
+    gl::Error invalidateSub(const gl::Context *context,
+                            size_t count,
                             const GLenum *attachments,
                             const gl::Rectangle &area) override;
 
@@ -46,8 +49,8 @@
                             GLfloat depth,
                             GLint stencil) override;
 
-    GLenum getImplementationColorReadFormat() const override;
-    GLenum getImplementationColorReadType() const override;
+    GLenum getImplementationColorReadFormat(const gl::Context *context) const override;
+    GLenum getImplementationColorReadType(const gl::Context *context) const override;
     gl::Error readPixels(const gl::Context *context,
                          const gl::Rectangle &area,
                          GLenum format,
diff --git a/src/libANGLE/renderer/null/ImageNULL.cpp b/src/libANGLE/renderer/null/ImageNULL.cpp
index d7bd6da..d106bf6 100644
--- a/src/libANGLE/renderer/null/ImageNULL.cpp
+++ b/src/libANGLE/renderer/null/ImageNULL.cpp
@@ -28,7 +28,7 @@
     return egl::EglBadAccess();
 }
 
-gl::Error ImageNULL::orphan(egl::ImageSibling *sibling)
+gl::Error ImageNULL::orphan(const gl::Context *context, egl::ImageSibling *sibling)
 {
     UNIMPLEMENTED();
     return gl::InternalError();
diff --git a/src/libANGLE/renderer/null/ImageNULL.h b/src/libANGLE/renderer/null/ImageNULL.h
index e332d00..012f840 100644
--- a/src/libANGLE/renderer/null/ImageNULL.h
+++ b/src/libANGLE/renderer/null/ImageNULL.h
@@ -22,7 +22,7 @@
     ~ImageNULL() override;
     egl::Error initialize() override;
 
-    gl::Error orphan(egl::ImageSibling *sibling) override;
+    gl::Error orphan(const gl::Context *context, egl::ImageSibling *sibling) override;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/null/TextureNULL.cpp b/src/libANGLE/renderer/null/TextureNULL.cpp
index a21ad9e..16145c0 100644
--- a/src/libANGLE/renderer/null/TextureNULL.cpp
+++ b/src/libANGLE/renderer/null/TextureNULL.cpp
@@ -102,12 +102,15 @@
     return gl::NoError();
 }
 
-gl::Error TextureNULL::setEGLImageTarget(GLenum target, egl::Image *image)
+gl::Error TextureNULL::setEGLImageTarget(const gl::Context *context,
+                                         GLenum target,
+                                         egl::Image *image)
 {
     return gl::NoError();
 }
 
-gl::Error TextureNULL::setImageExternal(GLenum target,
+gl::Error TextureNULL::setImageExternal(const gl::Context *context,
+                                        GLenum target,
                                         egl::Stream *stream,
                                         const egl::Stream::GLTextureDescription &desc)
 {
@@ -119,16 +122,19 @@
     return gl::NoError();
 }
 
-void TextureNULL::setBaseLevel(GLuint baseLevel)
+gl::Error TextureNULL::setBaseLevel(const gl::Context *context, GLuint baseLevel)
 {
+    return gl::NoError();
 }
 
-void TextureNULL::bindTexImage(egl::Surface *surface)
+gl::Error TextureNULL::bindTexImage(const gl::Context *context, egl::Surface *surface)
 {
+    return gl::NoError();
 }
 
-void TextureNULL::releaseTexImage()
+gl::Error TextureNULL::releaseTexImage(const gl::Context *context)
 {
+    return gl::NoError();
 }
 
 void TextureNULL::syncState(const gl::Texture::DirtyBits &dirtyBits)
diff --git a/src/libANGLE/renderer/null/TextureNULL.h b/src/libANGLE/renderer/null/TextureNULL.h
index a7e2752..8da3fcb 100644
--- a/src/libANGLE/renderer/null/TextureNULL.h
+++ b/src/libANGLE/renderer/null/TextureNULL.h
@@ -75,18 +75,21 @@
                          GLenum internalFormat,
                          const gl::Extents &size) override;
 
-    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+    gl::Error setEGLImageTarget(const gl::Context *context,
+                                GLenum target,
+                                egl::Image *image) override;
 
-    gl::Error setImageExternal(GLenum target,
+    gl::Error setImageExternal(const gl::Context *context,
+                               GLenum target,
                                egl::Stream *stream,
                                const egl::Stream::GLTextureDescription &desc) override;
 
     gl::Error generateMipmap(const gl::Context *context) override;
 
-    void setBaseLevel(GLuint baseLevel) override;
+    gl::Error setBaseLevel(const gl::Context *context, GLuint baseLevel) override;
 
-    void bindTexImage(egl::Surface *surface) override;
-    void releaseTexImage() override;
+    gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+    gl::Error releaseTexImage(const gl::Context *context) override;
 
     void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
 
diff --git a/src/libANGLE/renderer/null/TransformFeedbackNULL.cpp b/src/libANGLE/renderer/null/TransformFeedbackNULL.cpp
index b26f29a..177fda3 100644
--- a/src/libANGLE/renderer/null/TransformFeedbackNULL.cpp
+++ b/src/libANGLE/renderer/null/TransformFeedbackNULL.cpp
@@ -39,12 +39,12 @@
 {
 }
 
-void TransformFeedbackNULL::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
+void TransformFeedbackNULL::bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding)
 {
 }
 
 void TransformFeedbackNULL::bindIndexedBuffer(size_t index,
-                                              const OffsetBindingPointer<gl::Buffer> &binding)
+                                              const gl::OffsetBindingPointer<gl::Buffer> &binding)
 {
 }
 
diff --git a/src/libANGLE/renderer/null/TransformFeedbackNULL.h b/src/libANGLE/renderer/null/TransformFeedbackNULL.h
index 477e81d..e7f3dc5 100644
--- a/src/libANGLE/renderer/null/TransformFeedbackNULL.h
+++ b/src/libANGLE/renderer/null/TransformFeedbackNULL.h
@@ -26,8 +26,9 @@
     void pause() override;
     void resume() override;
 
-    void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
-    void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+    void bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding) override;
+    void bindIndexedBuffer(size_t index,
+                           const gl::OffsetBindingPointer<gl::Buffer> &binding) override;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/null/VertexArrayNULL.cpp b/src/libANGLE/renderer/null/VertexArrayNULL.cpp
index 95a835d..c2b6893 100644
--- a/src/libANGLE/renderer/null/VertexArrayNULL.cpp
+++ b/src/libANGLE/renderer/null/VertexArrayNULL.cpp
@@ -18,8 +18,4 @@
 {
 }
 
-VertexArrayNULL::~VertexArrayNULL()
-{
-}
-
 }  // namespace rx
diff --git a/src/libANGLE/renderer/null/VertexArrayNULL.h b/src/libANGLE/renderer/null/VertexArrayNULL.h
index f8b2b04..11b8e30 100644
--- a/src/libANGLE/renderer/null/VertexArrayNULL.h
+++ b/src/libANGLE/renderer/null/VertexArrayNULL.h
@@ -19,7 +19,6 @@
 {
   public:
     VertexArrayNULL(const gl::VertexArrayState &data);
-    ~VertexArrayNULL() override;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/renderer_utils.cpp b/src/libANGLE/renderer/renderer_utils.cpp
index 7773e35..863953b 100644
--- a/src/libANGLE/renderer/renderer_utils.cpp
+++ b/src/libANGLE/renderer/renderer_utils.cpp
@@ -170,6 +170,18 @@
 {
 }
 
+PackPixelsParams::PackPixelsParams(const gl::Context *context, const PackPixelsParams &other)
+    : area(other.area),
+      format(other.format),
+      type(other.type),
+      outputPitch(other.outputPitch),
+      packBuffer(other.packBuffer),
+      pack(),
+      offset(other.offset)
+{
+    pack.copyFrom(context, other.pack);
+}
+
 void PackPixels(const PackPixelsParams &params,
                 const angle::Format &sourceFormat,
                 int inputPitchIn,
diff --git a/src/libANGLE/renderer/renderer_utils.h b/src/libANGLE/renderer/renderer_utils.h
index 0936024..3817668 100644
--- a/src/libANGLE/renderer/renderer_utils.h
+++ b/src/libANGLE/renderer/renderer_utils.h
@@ -121,7 +121,7 @@
     const Entry *mData;
 };
 
-struct PackPixelsParams
+struct PackPixelsParams : private angle::NonCopyable
 {
     PackPixelsParams();
     PackPixelsParams(const gl::Rectangle &area,
@@ -130,6 +130,7 @@
                      GLuint outputPitch,
                      const gl::PixelPackState &pack,
                      ptrdiff_t offset);
+    PackPixelsParams(const gl::Context *context, const PackPixelsParams &other);
 
     gl::Rectangle area;
     GLenum format;
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
index f15804a..e6a3e29 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
@@ -61,7 +61,7 @@
     return gl::InternalError();
 }
 
-gl::Error ContextVk::initPipeline()
+gl::Error ContextVk::initPipeline(const gl::Context *context)
 {
     ASSERT(!mCurrentPipeline.valid());
 
@@ -228,7 +228,7 @@
 
     // TODO(jmadill): Dynamic state.
     vk::RenderPass *renderPass = nullptr;
-    ANGLE_TRY_RESULT(vkFBO->getRenderPass(device), renderPass);
+    ANGLE_TRY_RESULT(vkFBO->getRenderPass(context, device), renderPass);
     ASSERT(renderPass && renderPass->valid());
 
     vk::PipelineLayout *pipelineLayout = nullptr;
@@ -274,7 +274,7 @@
 
     if (!mCurrentPipeline.valid())
     {
-        ANGLE_TRY(initPipeline());
+        ANGLE_TRY(initPipeline(context));
         ASSERT(mCurrentPipeline.valid());
     }
 
@@ -316,7 +316,7 @@
 
     vk::CommandBuffer *commandBuffer = nullptr;
     ANGLE_TRY(mRenderer->getStartedCommandBuffer(&commandBuffer));
-    ANGLE_TRY(vkFBO->beginRenderPass(device, commandBuffer, queueSerial, state));
+    ANGLE_TRY(vkFBO->beginRenderPass(context, device, commandBuffer, queueSerial, state));
 
     commandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline);
     commandBuffer->bindVertexBuffers(0, vertexHandles, vertexOffsets);
@@ -459,7 +459,7 @@
     return GLint64();
 }
 
-void ContextVk::onMakeCurrent(const gl::ContextState & /*data*/)
+void ContextVk::onMakeCurrent(const gl::Context * /*context*/)
 {
 }
 
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.h b/src/libANGLE/renderer/vulkan/ContextVk.h
index 62ef8ff..b326bee 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.h
+++ b/src/libANGLE/renderer/vulkan/ContextVk.h
@@ -91,7 +91,7 @@
     GLint64 getTimestamp() override;
 
     // Context switching
-    void onMakeCurrent(const gl::ContextState &data) override;
+    void onMakeCurrent(const gl::Context *context) override;
 
     // Native capabilities, unmodified by gl::Context.
     const gl::Caps &getNativeCaps() const override;
@@ -149,7 +149,7 @@
                               GLuint numGroupsZ) override;
 
   private:
-    gl::Error initPipeline();
+    gl::Error initPipeline(const gl::Context *context);
 
     RendererVk *mRenderer;
     vk::Pipeline mCurrentPipeline;
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index f7b6d70..9561698 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -32,10 +32,11 @@
 {
 
 gl::ErrorOrResult<const gl::InternalFormat *> GetReadAttachmentInfo(
+    const gl::Context *context,
     const gl::FramebufferAttachment *readAttachment)
 {
     RenderTargetVk *renderTarget = nullptr;
-    ANGLE_TRY(readAttachment->getRenderTarget(&renderTarget));
+    ANGLE_TRY(readAttachment->getRenderTarget(context, &renderTarget));
 
     GLenum implFormat = renderTarget->format->format().fboImplementationInternalFormat;
     return &gl::GetSizedInternalFormatInfo(implFormat);
@@ -109,19 +110,24 @@
     mFramebuffer.destroy(device);
 }
 
-gl::Error FramebufferVk::discard(size_t count, const GLenum *attachments)
+gl::Error FramebufferVk::discard(const gl::Context *context,
+                                 size_t count,
+                                 const GLenum *attachments)
 {
     UNIMPLEMENTED();
     return gl::InternalError();
 }
 
-gl::Error FramebufferVk::invalidate(size_t count, const GLenum *attachments)
+gl::Error FramebufferVk::invalidate(const gl::Context *context,
+                                    size_t count,
+                                    const GLenum *attachments)
 {
     UNIMPLEMENTED();
     return gl::InternalError();
 }
 
-gl::Error FramebufferVk::invalidateSub(size_t count,
+gl::Error FramebufferVk::invalidateSub(const gl::Context *context,
+                                       size_t count,
                                        const GLenum *attachments,
                                        const gl::Rectangle &area)
 {
@@ -172,7 +178,7 @@
         if (colorAttachment.isAttached())
         {
             RenderTargetVk *renderTarget = nullptr;
-            ANGLE_TRY(colorAttachment.getRenderTarget(&renderTarget));
+            ANGLE_TRY(colorAttachment.getRenderTarget(context, &renderTarget));
             renderTarget->image->changeLayoutTop(
                 VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, commandBuffer);
             commandBuffer->clearSingleColorImage(*renderTarget->image, clearColorValue);
@@ -219,9 +225,9 @@
     return gl::InternalError();
 }
 
-GLenum FramebufferVk::getImplementationColorReadFormat() const
+GLenum FramebufferVk::getImplementationColorReadFormat(const gl::Context *context) const
 {
-    auto errOrResult = GetReadAttachmentInfo(mState.getReadAttachment());
+    auto errOrResult = GetReadAttachmentInfo(context, mState.getReadAttachment());
 
     // TODO(jmadill): Handle getRenderTarget error.
     if (errOrResult.isError())
@@ -233,9 +239,9 @@
     return errOrResult.getResult()->format;
 }
 
-GLenum FramebufferVk::getImplementationColorReadType() const
+GLenum FramebufferVk::getImplementationColorReadType(const gl::Context *context) const
 {
-    auto errOrResult = GetReadAttachmentInfo(mState.getReadAttachment());
+    auto errOrResult = GetReadAttachmentInfo(context, mState.getReadAttachment());
 
     // TODO(jmadill): Handle getRenderTarget error.
     if (errOrResult.isError())
@@ -258,7 +264,7 @@
     const auto *readAttachment  = readFramebuffer->getReadColorbuffer();
 
     RenderTargetVk *renderTarget = nullptr;
-    ANGLE_TRY(readAttachment->getRenderTarget(&renderTarget));
+    ANGLE_TRY(readAttachment->getRenderTarget(context, &renderTarget));
 
     ContextVk *contextVk = GetImplAs<ContextVk>(context);
     RendererVk *renderer = contextVk->getRenderer();
@@ -306,7 +312,7 @@
     params.format      = format;
     params.type        = type;
     params.outputPitch = inputPitch;
-    params.pack        = glState.getPackState();
+    params.pack.copyFrom(context, glState.getPackState());
 
     PackPixels(params, angleFormat, inputPitch, mapPointer, reinterpret_cast<uint8_t *>(pixels));
 
@@ -351,7 +357,8 @@
     contextVk->invalidateCurrentPipeline();
 }
 
-gl::ErrorOrResult<vk::RenderPass *> FramebufferVk::getRenderPass(VkDevice device)
+gl::ErrorOrResult<vk::RenderPass *> FramebufferVk::getRenderPass(const gl::Context *context,
+                                                                 VkDevice device)
 {
     if (mRenderPass.valid())
     {
@@ -372,7 +379,7 @@
             VkAttachmentReference colorRef;
 
             RenderTargetVk *renderTarget = nullptr;
-            ANGLE_TRY(colorAttachment.getRenderTarget(&renderTarget));
+            ANGLE_TRY(colorAttachment.getRenderTarget(context, &renderTarget));
 
             // TODO(jmadill): We would only need this flag for duplicated attachments.
             colorDesc.flags   = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
@@ -407,7 +414,7 @@
         VkAttachmentDescription depthStencilDesc;
 
         RenderTargetVk *renderTarget = nullptr;
-        ANGLE_TRY(depthStencilAttachment->getRenderTarget(&renderTarget));
+        ANGLE_TRY(depthStencilAttachment->getRenderTarget(context, &renderTarget));
 
         depthStencilDesc.flags          = 0;
         depthStencilDesc.format         = renderTarget->format->native;
@@ -460,7 +467,8 @@
     return &mRenderPass;
 }
 
-gl::ErrorOrResult<vk::Framebuffer *> FramebufferVk::getFramebuffer(VkDevice device)
+gl::ErrorOrResult<vk::Framebuffer *> FramebufferVk::getFramebuffer(const gl::Context *context,
+                                                                   VkDevice device)
 {
     // If we've already created our cached Framebuffer, return it.
     if (mFramebuffer.valid())
@@ -469,7 +477,7 @@
     }
 
     vk::RenderPass *renderPass = nullptr;
-    ANGLE_TRY_RESULT(getRenderPass(device), renderPass);
+    ANGLE_TRY_RESULT(getRenderPass(context, device), renderPass);
 
     // If we've a Framebuffer provided by a Surface (default FBO/backbuffer), query it.
     if (mBackbuffer)
@@ -488,7 +496,7 @@
         if (colorAttachment.isAttached())
         {
             RenderTargetVk *renderTarget = nullptr;
-            ANGLE_TRY(colorAttachment.getRenderTarget<RenderTargetVk>(&renderTarget));
+            ANGLE_TRY(colorAttachment.getRenderTarget<RenderTargetVk>(context, &renderTarget));
             attachments.push_back(renderTarget->imageView->getHandle());
 
             ASSERT(attachmentsSize.empty() || attachmentsSize == colorAttachment.getSize());
@@ -500,7 +508,7 @@
     if (depthStencilAttachment && depthStencilAttachment->isAttached())
     {
         RenderTargetVk *renderTarget = nullptr;
-        ANGLE_TRY(depthStencilAttachment->getRenderTarget<RenderTargetVk>(&renderTarget));
+        ANGLE_TRY(depthStencilAttachment->getRenderTarget<RenderTargetVk>(context, &renderTarget));
         attachments.push_back(renderTarget->imageView->getHandle());
 
         ASSERT(attachmentsSize.empty() || attachmentsSize == depthStencilAttachment->getSize());
@@ -535,7 +543,8 @@
     return gl::InternalError() << "getSamplePosition is unimplemented.";
 }
 
-gl::Error FramebufferVk::beginRenderPass(VkDevice device,
+gl::Error FramebufferVk::beginRenderPass(const gl::Context *context,
+                                         VkDevice device,
                                          vk::CommandBuffer *commandBuffer,
                                          Serial queueSerial,
                                          const gl::State &glState)
@@ -546,7 +555,7 @@
         if (colorAttachment.isAttached())
         {
             RenderTargetVk *renderTarget = nullptr;
-            ANGLE_TRY(colorAttachment.getRenderTarget<RenderTargetVk>(&renderTarget));
+            ANGLE_TRY(colorAttachment.getRenderTarget<RenderTargetVk>(context, &renderTarget));
             renderTarget->resource->setQueueSerial(queueSerial);
         }
     }
@@ -555,16 +564,16 @@
     if (depthStencilAttachment && depthStencilAttachment->isAttached())
     {
         RenderTargetVk *renderTarget = nullptr;
-        ANGLE_TRY(depthStencilAttachment->getRenderTarget<RenderTargetVk>(&renderTarget));
+        ANGLE_TRY(depthStencilAttachment->getRenderTarget<RenderTargetVk>(context, &renderTarget));
         renderTarget->resource->setQueueSerial(queueSerial);
     }
 
     vk::Framebuffer *framebuffer = nullptr;
-    ANGLE_TRY_RESULT(getFramebuffer(device), framebuffer);
+    ANGLE_TRY_RESULT(getFramebuffer(context, device), framebuffer);
     ASSERT(framebuffer && framebuffer->valid());
 
     vk::RenderPass *renderPass = nullptr;
-    ANGLE_TRY_RESULT(getRenderPass(device), renderPass);
+    ANGLE_TRY_RESULT(getRenderPass(context, device), renderPass);
     ASSERT(renderPass && renderPass->valid());
 
     // TODO(jmadill): Proper clear value implementation.
@@ -583,7 +592,7 @@
     // TODO(jmadill): Iterate over all attachments.
     ASSERT(mBackbuffer);
     RenderTargetVk *renderTarget = nullptr;
-    ANGLE_TRY(mState.getFirstColorAttachment()->getRenderTarget(&renderTarget));
+    ANGLE_TRY(mState.getFirstColorAttachment()->getRenderTarget(context, &renderTarget));
     renderTarget->image->updateLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
 
     commandBuffer->beginRenderPass(*renderPass, *framebuffer, glState.getViewport(),
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.h b/src/libANGLE/renderer/vulkan/FramebufferVk.h
index 01926b5..f3b8b0a 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.h
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.h
@@ -34,9 +34,12 @@
     void destroy(const gl::Context *context) override;
     void destroyDefault(const egl::Display *display) override;
 
-    gl::Error discard(size_t count, const GLenum *attachments) override;
-    gl::Error invalidate(size_t count, const GLenum *attachments) override;
-    gl::Error invalidateSub(size_t count,
+    gl::Error discard(const gl::Context *context, size_t count, const GLenum *attachments) override;
+    gl::Error invalidate(const gl::Context *context,
+                         size_t count,
+                         const GLenum *attachments) override;
+    gl::Error invalidateSub(const gl::Context *context,
+                            size_t count,
                             const GLenum *attachments,
                             const gl::Rectangle &area) override;
 
@@ -59,8 +62,8 @@
                             GLfloat depth,
                             GLint stencil) override;
 
-    GLenum getImplementationColorReadFormat() const override;
-    GLenum getImplementationColorReadType() const override;
+    GLenum getImplementationColorReadFormat(const gl::Context *context) const override;
+    GLenum getImplementationColorReadType(const gl::Context *context) const override;
     gl::Error readPixels(const gl::Context *context,
                          const gl::Rectangle &area,
                          GLenum format,
@@ -80,18 +83,20 @@
 
     gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
 
-    gl::Error beginRenderPass(VkDevice device,
+    gl::Error beginRenderPass(const gl::Context *context,
+                              VkDevice device,
                               vk::CommandBuffer *commandBuffer,
                               Serial queueSerial,
                               const gl::State &glState);
 
-    gl::ErrorOrResult<vk::RenderPass *> getRenderPass(VkDevice device);
+    gl::ErrorOrResult<vk::RenderPass *> getRenderPass(const gl::Context *context, VkDevice device);
 
   private:
     FramebufferVk(const gl::FramebufferState &state);
     FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer);
 
-    gl::ErrorOrResult<vk::Framebuffer *> getFramebuffer(VkDevice device);
+    gl::ErrorOrResult<vk::Framebuffer *> getFramebuffer(const gl::Context *context,
+                                                        VkDevice device);
 
     WindowSurfaceVk *mBackbuffer;
 
diff --git a/src/libANGLE/renderer/vulkan/GlslangWrapper.h b/src/libANGLE/renderer/vulkan/GlslangWrapper.h
index 65b714e..a84437f 100644
--- a/src/libANGLE/renderer/vulkan/GlslangWrapper.h
+++ b/src/libANGLE/renderer/vulkan/GlslangWrapper.h
@@ -15,7 +15,7 @@
 namespace rx
 {
 
-class GlslangWrapper : public RefCountObjectNoID
+class GlslangWrapper : public gl::RefCountObjectNoID
 {
   public:
     // Increases the reference count.
diff --git a/src/libANGLE/renderer/vulkan/ImageVk.cpp b/src/libANGLE/renderer/vulkan/ImageVk.cpp
index 4d27e70..3709da1 100644
--- a/src/libANGLE/renderer/vulkan/ImageVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ImageVk.cpp
@@ -28,7 +28,7 @@
     return egl::EglBadAccess();
 }
 
-gl::Error ImageVk::orphan(egl::ImageSibling *sibling)
+gl::Error ImageVk::orphan(const gl::Context *context, egl::ImageSibling *sibling)
 {
     UNIMPLEMENTED();
     return gl::InternalError();
diff --git a/src/libANGLE/renderer/vulkan/ImageVk.h b/src/libANGLE/renderer/vulkan/ImageVk.h
index 85672f9..5781c80 100644
--- a/src/libANGLE/renderer/vulkan/ImageVk.h
+++ b/src/libANGLE/renderer/vulkan/ImageVk.h
@@ -22,7 +22,7 @@
     ~ImageVk() override;
     egl::Error initialize() override;
 
-    gl::Error orphan(egl::ImageSibling *sibling) override;
+    gl::Error orphan(const gl::Context *context, egl::ImageSibling *sibling) override;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
index 155ee6d..0b0f7fe 100644
--- a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
@@ -43,7 +43,8 @@
     return gl::InternalError();
 }
 
-gl::Error RenderbufferVk::getAttachmentRenderTarget(GLenum binding,
+gl::Error RenderbufferVk::getAttachmentRenderTarget(const gl::Context *context,
+                                                    GLenum binding,
                                                     const gl::ImageIndex &imageIndex,
                                                     FramebufferAttachmentRenderTarget **rtOut)
 {
diff --git a/src/libANGLE/renderer/vulkan/RenderbufferVk.h b/src/libANGLE/renderer/vulkan/RenderbufferVk.h
index 95ce8bb..cd3b58e 100644
--- a/src/libANGLE/renderer/vulkan/RenderbufferVk.h
+++ b/src/libANGLE/renderer/vulkan/RenderbufferVk.h
@@ -28,7 +28,8 @@
                                     size_t height) override;
     gl::Error setStorageEGLImageTarget(egl::Image *image) override;
 
-    gl::Error getAttachmentRenderTarget(GLenum binding,
+    gl::Error getAttachmentRenderTarget(const gl::Context *context,
+                                        GLenum binding,
                                         const gl::ImageIndex &imageIndex,
                                         FramebufferAttachmentRenderTarget **rtOut) override;
 };
diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
index cd0ee50..9deaff1 100644
--- a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
+++ b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
@@ -141,6 +141,7 @@
 }
 
 gl::Error OffscreenSurfaceVk::getAttachmentRenderTarget(
+    const gl::Context * /*context*/,
     GLenum /*binding*/,
     const gl::ImageIndex & /*imageIndex*/,
     FramebufferAttachmentRenderTarget ** /*rtOut*/)
@@ -529,7 +530,8 @@
     return EGL_BUFFER_DESTROYED;
 }
 
-gl::Error WindowSurfaceVk::getAttachmentRenderTarget(GLenum /*binding*/,
+gl::Error WindowSurfaceVk::getAttachmentRenderTarget(const gl::Context * /*context*/,
+                                                     GLenum /*binding*/,
                                                      const gl::ImageIndex & /*target*/,
                                                      FramebufferAttachmentRenderTarget **rtOut)
 {
diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.h b/src/libANGLE/renderer/vulkan/SurfaceVk.h
index 227a23c..48ed2f1 100644
--- a/src/libANGLE/renderer/vulkan/SurfaceVk.h
+++ b/src/libANGLE/renderer/vulkan/SurfaceVk.h
@@ -47,7 +47,8 @@
     EGLint isPostSubBufferSupported() const override;
     EGLint getSwapBehavior() const override;
 
-    gl::Error getAttachmentRenderTarget(GLenum binding,
+    gl::Error getAttachmentRenderTarget(const gl::Context *context,
+                                        GLenum binding,
                                         const gl::ImageIndex &imageIndex,
                                         FramebufferAttachmentRenderTarget **rtOut) override;
 
@@ -88,7 +89,8 @@
     EGLint isPostSubBufferSupported() const override;
     EGLint getSwapBehavior() const override;
 
-    gl::Error getAttachmentRenderTarget(GLenum binding,
+    gl::Error getAttachmentRenderTarget(const gl::Context *context,
+                                        GLenum binding,
                                         const gl::ImageIndex &imageIndex,
                                         FramebufferAttachmentRenderTarget **rtOut) override;
 
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
index f477156..bd5617d 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -107,13 +107,14 @@
     return gl::InternalError();
 }
 
-gl::Error TextureVk::setEGLImageTarget(GLenum target, egl::Image *image)
+gl::Error TextureVk::setEGLImageTarget(const gl::Context *context, GLenum target, egl::Image *image)
 {
     UNIMPLEMENTED();
     return gl::InternalError();
 }
 
-gl::Error TextureVk::setImageExternal(GLenum target,
+gl::Error TextureVk::setImageExternal(const gl::Context *context,
+                                      GLenum target,
                                       egl::Stream *stream,
                                       const egl::Stream::GLTextureDescription &desc)
 {
@@ -127,22 +128,26 @@
     return gl::InternalError();
 }
 
-void TextureVk::setBaseLevel(GLuint baseLevel)
+gl::Error TextureVk::setBaseLevel(const gl::Context *context, GLuint baseLevel)
 {
     UNIMPLEMENTED();
+    return gl::InternalError();
 }
 
-void TextureVk::bindTexImage(egl::Surface *surface)
+gl::Error TextureVk::bindTexImage(const gl::Context *context, egl::Surface *surface)
 {
     UNIMPLEMENTED();
+    return gl::InternalError();
 }
 
-void TextureVk::releaseTexImage()
+gl::Error TextureVk::releaseTexImage(const gl::Context *context)
 {
     UNIMPLEMENTED();
+    return gl::InternalError();
 }
 
-gl::Error TextureVk::getAttachmentRenderTarget(GLenum binding,
+gl::Error TextureVk::getAttachmentRenderTarget(const gl::Context *context,
+                                               GLenum binding,
                                                const gl::ImageIndex &imageIndex,
                                                FramebufferAttachmentRenderTarget **rtOut)
 {
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.h b/src/libANGLE/renderer/vulkan/TextureVk.h
index d50854e..70e8651 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.h
+++ b/src/libANGLE/renderer/vulkan/TextureVk.h
@@ -75,20 +75,24 @@
                          GLenum internalFormat,
                          const gl::Extents &size) override;
 
-    gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+    gl::Error setEGLImageTarget(const gl::Context *context,
+                                GLenum target,
+                                egl::Image *image) override;
 
-    gl::Error setImageExternal(GLenum target,
+    gl::Error setImageExternal(const gl::Context *context,
+                               GLenum target,
                                egl::Stream *stream,
                                const egl::Stream::GLTextureDescription &desc) override;
 
     gl::Error generateMipmap(const gl::Context *context) override;
 
-    void setBaseLevel(GLuint baseLevel) override;
+    gl::Error setBaseLevel(const gl::Context *context, GLuint baseLevel) override;
 
-    void bindTexImage(egl::Surface *surface) override;
-    void releaseTexImage() override;
+    gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+    gl::Error releaseTexImage(const gl::Context *context) override;
 
-    gl::Error getAttachmentRenderTarget(GLenum binding,
+    gl::Error getAttachmentRenderTarget(const gl::Context *context,
+                                        GLenum binding,
                                         const gl::ImageIndex &imageIndex,
                                         FramebufferAttachmentRenderTarget **rtOut) override;
 
diff --git a/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp b/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp
index ea445c7..5e80078 100644
--- a/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp
@@ -43,13 +43,13 @@
     UNIMPLEMENTED();
 }
 
-void TransformFeedbackVk::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
+void TransformFeedbackVk::bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding)
 {
     UNIMPLEMENTED();
 }
 
 void TransformFeedbackVk::bindIndexedBuffer(size_t index,
-                                            const OffsetBindingPointer<gl::Buffer> &binding)
+                                            const gl::OffsetBindingPointer<gl::Buffer> &binding)
 {
     UNIMPLEMENTED();
 }
diff --git a/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h b/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h
index ed8522c..a379b36 100644
--- a/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h
+++ b/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h
@@ -26,8 +26,9 @@
     void pause() override;
     void resume() override;
 
-    void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
-    void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
+    void bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding) override;
+    void bindIndexedBuffer(size_t index,
+                           const gl::OffsetBindingPointer<gl::Buffer> &binding) override;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
index 0aabb4a..c00cb36 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
@@ -21,7 +21,7 @@
 {
 }
 
-VertexArrayVk::~VertexArrayVk()
+void VertexArrayVk::destroy(const gl::Context *context)
 {
 }
 
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.h b/src/libANGLE/renderer/vulkan/VertexArrayVk.h
index 63f9ffa..43f29b7 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.h
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.h
@@ -19,7 +19,7 @@
 {
   public:
     VertexArrayVk(const gl::VertexArrayState &data);
-    ~VertexArrayVk() override;
+    void destroy(const gl::Context *context) override;
 
     void syncState(const gl::Context *context,
                    const gl::VertexArray::DirtyBits &dirtyBits) override;
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 1fa15f0..30044f5 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -1729,7 +1729,7 @@
     return true;
 }
 
-bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
+bool ValidateReadPixelsRobustANGLE(Context *context,
                                    GLint x,
                                    GLint y,
                                    GLsizei width,
@@ -1781,7 +1781,7 @@
                                   nullptr, nullptr, pixels);
 }
 
-bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
+bool ValidateReadnPixelsRobustANGLE(Context *context,
                                     GLint x,
                                     GLint y,
                                     GLsizei width,
@@ -5232,7 +5232,7 @@
     return true;
 }
 
-bool ValidateReadPixelsBase(ValidationContext *context,
+bool ValidateReadPixelsBase(Context *context,
                             GLint x,
                             GLint y,
                             GLsizei width,
@@ -5298,8 +5298,8 @@
         return false;
     }
 
-    GLenum currentFormat        = framebuffer->getImplementationColorReadFormat();
-    GLenum currentType          = framebuffer->getImplementationColorReadType();
+    GLenum currentFormat        = framebuffer->getImplementationColorReadFormat(context);
+    GLenum currentType          = framebuffer->getImplementationColorReadType(context);
     GLenum currentComponentType = readBuffer->getFormat().info->componentType;
 
     bool validFormatTypeCombination =
diff --git a/src/libANGLE/validationES.h b/src/libANGLE/validationES.h
index 04eeea2..9ab3624 100644
--- a/src/libANGLE/validationES.h
+++ b/src/libANGLE/validationES.h
@@ -114,7 +114,7 @@
                                        GLbitfield mask,
                                        GLenum filter);
 
-bool ValidateReadPixelsBase(ValidationContext *context,
+bool ValidateReadPixelsBase(Context *context,
                             GLint x,
                             GLint y,
                             GLsizei width,
@@ -126,7 +126,7 @@
                             GLsizei *columns,
                             GLsizei *rows,
                             void *pixels);
-bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
+bool ValidateReadPixelsRobustANGLE(Context *context,
                                    GLint x,
                                    GLint y,
                                    GLsizei width,
@@ -147,7 +147,7 @@
                             GLenum type,
                             GLsizei bufSize,
                             void *pixels);
-bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
+bool ValidateReadnPixelsRobustANGLE(Context *context,
                                     GLint x,
                                     GLint y,
                                     GLsizei width,
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
index 0fc6423..8bd1469 100644
--- a/src/libANGLE/validationES2.cpp
+++ b/src/libANGLE/validationES2.cpp
@@ -5922,7 +5922,7 @@
     return true;
 }
 
-bool ValidateReadPixels(ValidationContext *context,
+bool ValidateReadPixels(Context *context,
                         GLint x,
                         GLint y,
                         GLsizei width,
diff --git a/src/libANGLE/validationES2.h b/src/libANGLE/validationES2.h
index e6ae180..b6c3ddd 100644
--- a/src/libANGLE/validationES2.h
+++ b/src/libANGLE/validationES2.h
@@ -658,7 +658,7 @@
 bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer);
 bool ValidateIsEnabled(Context *context, GLenum cap);
 bool ValidateLinkProgram(Context *context, GLuint program);
-bool ValidateReadPixels(ValidationContext *context,
+bool ValidateReadPixels(Context *context,
                         GLint x,
                         GLint y,
                         GLsizei width,
diff --git a/src/libANGLE/validationES_unittest.cpp b/src/libANGLE/validationES_unittest.cpp
index cf2ba1e..ca27a36 100644
--- a/src/libANGLE/validationES_unittest.cpp
+++ b/src/libANGLE/validationES_unittest.cpp
@@ -58,6 +58,7 @@
 // larger than MAX_ELEMENT_INDEX. Not specified in the GLES 3 spec, it's undefined behaviour,
 // but we want a test to ensure we maintain this behaviour.
 // TODO(jmadill): Re-enable when framebuffer sync state doesn't happen in validation.
+// Also broken because of change of api of the state initialize method.
 TEST(ValidationESTest, DISABLED_DrawElementsWithMaxIndexGivesError)
 {
     auto framebufferImpl = MakeFramebufferMock();
@@ -79,7 +80,7 @@
     caps.maxElementIndex     = 100;
     caps.maxDrawBuffers      = 1;
     caps.maxColorAttachments = 1;
-    state.initialize(caps, extensions, Version(3, 0), false, true, true, false);
+    state.initialize(nullptr, false, true, true, false);
 
     NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>();
     EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
@@ -116,15 +117,15 @@
     EXPECT_FALSE(
         ValidateDrawElementsCommon(&testContext, GL_TRIANGLES, 6, GL_UNSIGNED_INT, indexData, 2));
 
-    texture->release();
+    texture->release(nullptr);
 
     state.setVertexArrayBinding(nullptr);
     state.setDrawFramebufferBinding(nullptr);
     state.setProgram(nullptr, nullptr);
 
-    SafeDelete(vertexArray);
-    SafeDelete(framebuffer);
-    SafeDelete(program);
+    vertexArray->onDestroy(nullptr);
+    framebuffer->onDestroy(nullptr);
+    program->onDestroy(nullptr);
 }
 
 }  // anonymous namespace
diff --git a/src/libGLESv2/entry_points_egl.cpp b/src/libGLESv2/entry_points_egl.cpp
index 6b9a1d4..5903f72 100644
--- a/src/libGLESv2/entry_points_egl.cpp
+++ b/src/libGLESv2/entry_points_egl.cpp
@@ -118,7 +118,12 @@
         thread->setCurrent(nullptr);
     }
 
-    display->terminate();
+    Error error = display->terminate();
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
 
     thread->setError(NoError());
     return EGL_TRUE;
@@ -366,7 +371,12 @@
         return EGL_FALSE;
     }
 
-    display->destroySurface((Surface *)surface);
+    error = display->destroySurface(reinterpret_cast<Surface *>(surface));
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
 
     thread->setError(NoError());
     return EGL_TRUE;
@@ -567,7 +577,12 @@
         thread->setCurrent(nullptr);
     }
 
-    display->destroyContext(context);
+    error = display->destroyContext(context);
+    if (error.isError())
+    {
+        thread->setError(error);
+        return EGL_FALSE;
+    }
 
     thread->setError(NoError());
     return EGL_TRUE;
@@ -607,7 +622,12 @@
     // destroyed surfaces to delete themselves.
     if (previousContext != nullptr && context != previousContext)
     {
-        previousContext->releaseSurface(display);
+        auto err = previousContext->releaseSurface(display);
+        if (err.isError())
+        {
+            thread->setError(err);
+            return EGL_FALSE;
+        }
     }
 
     thread->setError(NoError());
@@ -874,7 +894,7 @@
             return EGL_FALSE;
         }
 
-        error = eglSurface->bindTexImage(textureObject, buffer);
+        error = eglSurface->bindTexImage(context, textureObject, buffer);
         if (error.isError())
         {
             thread->setError(error);
@@ -951,7 +971,7 @@
 
     if (texture)
     {
-        error = eglSurface->releaseTexImage(buffer);
+        error = eglSurface->releaseTexImage(thread->getContext(), buffer);
         if (error.isError())
         {
             thread->setError(error);
diff --git a/src/libGLESv2/entry_points_egl_ext.cpp b/src/libGLESv2/entry_points_egl_ext.cpp
index 4de7595..e8f1910 100644
--- a/src/libGLESv2/entry_points_egl_ext.cpp
+++ b/src/libGLESv2/entry_points_egl_ext.cpp
@@ -586,7 +586,7 @@
         return EGL_FALSE;
     }
 
-    error = streamObject->consumerAcquire();
+    error = streamObject->consumerAcquire(context);
     if (error.isError())
     {
         thread->setError(error);
@@ -613,7 +613,7 @@
         return EGL_FALSE;
     }
 
-    error = streamObject->consumerRelease();
+    error = streamObject->consumerRelease(context);
     if (error.isError())
     {
         thread->setError(error);
diff --git a/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
index aee5304..f48cb90 100644
--- a/src/libGLESv2/entry_points_gles_2_0_ext.cpp
+++ b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
@@ -1033,7 +1033,7 @@
         }
 
         Texture *texture = context->getTargetTexture(target);
-        Error error      = texture->setEGLImageTarget(target, imageObject);
+        Error error      = texture->setEGLImageTarget(context, target, imageObject);
         if (error.isError())
         {
             context->handleError(error);
@@ -1057,7 +1057,7 @@
         }
 
         Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
-        Error error                = renderbuffer->setStorageEGLImageTarget(imageObject);
+        Error error                = renderbuffer->setStorageEGLImageTarget(context, imageObject);
         if (error.isError())
         {
             context->handleError(error);
@@ -2488,7 +2488,7 @@
         }
 
         Texture *texture = context->getTargetTexture(target);
-        SetTexParameterfv(texture, pname, params);
+        SetTexParameterfv(context, texture, pname, params);
     }
 }
 
@@ -2511,7 +2511,7 @@
         }
 
         Texture *texture = context->getTargetTexture(target);
-        SetTexParameteriv(texture, pname, params);
+        SetTexParameteriv(context, texture, pname, params);
     }
 }