From c6df5fe3ed0f2a722931be098914978cf17a666f Mon Sep 17 00:00:00 2001
From: Andrew Knight <andrew.knight@theqtcompany.com>
Date: Fri, 14 Nov 2014 10:52:01 +0200
Subject: [PATCH] ANGLE: Upgrade to version 1.2.30d6c255d238

The following patches have been changed:

0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch
  Removed because it is no longer possible to build ANGLE with MSVC2008

0002-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch
  Removed because the minimum version of MinGW moved to 4.8.2

0005-Fix-build-when-SSE2-is-not-available.patch
  Removed because it was fixed upstream

0006-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch
  Removed because older versions of MinGW are not supported

0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch
  Removed because it was fixed upstream

Task-number: QTBUG-41903
Change-Id: I976d30802f7f6fee725cf9a9f1325d5e82609835
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com>
Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com>
---
 src/3rdparty/angle/AUTHORS                    |    2 +
 src/3rdparty/angle/CONTRIBUTORS               |    5 +
 src/3rdparty/angle/include/EGL/egl.h          |    2 +-
 src/3rdparty/angle/include/EGL/eglext.h       |   16 +-
 src/3rdparty/angle/include/EGL/eglplatform.h  |   19 +-
 .../angle/include/GLSLANG/ShaderLang.h        |  210 +-
 .../angle/include/GLSLANG/ShaderVars.h        |   64 +-
 .../angle/include/angle_windowsstore.h        |   37 +
 src/3rdparty/angle/src/commit.h               |    4 +-
 src/3rdparty/angle/src/common/NativeWindow.h  |   77 +
 src/3rdparty/angle/src/common/angleutils.cpp  |   25 +-
 src/3rdparty/angle/src/common/angleutils.h    |   11 +
 src/3rdparty/angle/src/common/debug.cpp       |  242 +-
 src/3rdparty/angle/src/common/debug.h         |   19 +-
 src/3rdparty/angle/src/common/features.h      |   35 +
 src/3rdparty/angle/src/common/mathutil.h      |    4 +-
 src/3rdparty/angle/src/common/platform.h      |   89 +-
 src/3rdparty/angle/src/common/tls.cpp         |  107 +-
 src/3rdparty/angle/src/common/tls.h           |   17 +-
 src/3rdparty/angle/src/common/utilities.cpp   |   89 +-
 src/3rdparty/angle/src/common/utilities.h     |    6 +
 .../angle/src/common/win32/NativeWindow.cpp   |   66 +
 .../common/winrt/CoreWindowNativeWindow.cpp   |  200 ++
 .../src/common/winrt/CoreWindowNativeWindow.h |   39 +
 .../common/winrt/InspectableNativeWindow.cpp  |  274 ++
 .../common/winrt/InspectableNativeWindow.h    |   91 +
 .../winrt/SwapChainPanelNativeWindow.cpp      |  226 ++
 .../common/winrt/SwapChainPanelNativeWindow.h |   79 +
 .../preprocessor/DirectiveHandlerBase.h       |    3 +-
 .../compiler/preprocessor/DirectiveParser.cpp |   35 +-
 .../compiler/preprocessor/MacroExpander.cpp   |    4 +-
 .../src/compiler/translator/Compiler.cpp      |   63 +-
 .../angle/src/compiler/translator/Compiler.h  |   10 +-
 .../translator/DetectDiscontinuity.cpp        |   52 +
 .../compiler/translator/DetectDiscontinuity.h |   19 +
 .../compiler/translator/DirectiveHandler.cpp  |   79 +-
 .../compiler/translator/DirectiveHandler.h    |    3 +-
 .../src/compiler/translator/IntermNode.cpp    |   76 +
 .../src/compiler/translator/IntermNode.h      |    5 +
 .../src/compiler/translator/Intermediate.cpp  |    1 +
 .../compiler/translator/OutputGLSLBase.cpp    |   18 +-
 .../src/compiler/translator/OutputHLSL.cpp    |   57 +-
 .../src/compiler/translator/OutputHLSL.h      |    1 +
 .../src/compiler/translator/ParseContext.cpp  |   13 +-
 .../src/compiler/translator/ParseContext.h    |    2 +-
 .../angle/src/compiler/translator/Pragma.h    |   12 +-
 .../src/compiler/translator/ShaderLang.cpp    |  371 +--
 .../src/compiler/translator/ShaderVars.cpp    |  165 ++
 .../src/compiler/translator/SymbolTable.h     |   41 +-
 .../compiler/translator/TranslatorESSL.cpp    |   11 +-
 .../compiler/translator/TranslatorGLSL.cpp    |   30 +-
 .../src/compiler/translator/TranslatorGLSL.h  |   12 +-
 .../translator/ValidateLimitations.cpp        |    1 +
 .../src/compiler/translator/VariableInfo.cpp  |   81 +-
 .../src/compiler/translator/VariableInfo.h    |   17 +-
 .../src/compiler/translator/VersionGLSL.cpp   |   16 +-
 .../src/compiler/translator/VersionGLSL.h     |    4 +-
 .../angle/src/compiler/translator/glslang.y   |   34 +-
 .../src/compiler/translator/intermOut.cpp     |    6 +-
 .../angle/src/compiler/translator/util.cpp    |   47 +-
 .../angle/src/compiler/translator/util.h      |   12 +-
 .../angle/src/libEGL/AttributeMap.cpp         |   40 +
 src/3rdparty/angle/src/libEGL/AttributeMap.h  |   33 +
 src/3rdparty/angle/src/libEGL/Display.cpp     |  169 +-
 src/3rdparty/angle/src/libEGL/Display.h       |   22 +-
 src/3rdparty/angle/src/libEGL/Error.cpp       |   48 +
 src/3rdparty/angle/src/libEGL/Error.h         |   39 +
 src/3rdparty/angle/src/libEGL/Surface.cpp     |  339 +--
 src/3rdparty/angle/src/libEGL/Surface.h       |   60 +-
 src/3rdparty/angle/src/libEGL/libEGL.cpp      |  465 +++-
 src/3rdparty/angle/src/libEGL/main.cpp        |   40 +-
 src/3rdparty/angle/src/libEGL/main.h          |   22 +-
 .../angle/src/libGLESv2/BinaryStream.h        |   12 +-
 src/3rdparty/angle/src/libGLESv2/Buffer.h     |    1 -
 src/3rdparty/angle/src/libGLESv2/Context.cpp  |  865 +------
 src/3rdparty/angle/src/libGLESv2/Context.h    |   62 +-
 src/3rdparty/angle/src/libGLESv2/Data.cpp     |   51 +
 src/3rdparty/angle/src/libGLESv2/Data.h       |   38 +
 src/3rdparty/angle/src/libGLESv2/Fence.cpp    |  176 +-
 src/3rdparty/angle/src/libGLESv2/Fence.h      |   35 +-
 .../angle/src/libGLESv2/Framebuffer.cpp       |  277 +-
 .../angle/src/libGLESv2/Framebuffer.h         |   50 +-
 .../src/libGLESv2/FramebufferAttachment.cpp   |    2 +-
 .../src/libGLESv2/FramebufferAttachment.h     |    7 -
 .../angle/src/libGLESv2/ImageIndex.cpp        |   91 +
 src/3rdparty/angle/src/libGLESv2/ImageIndex.h |   29 +-
 src/3rdparty/angle/src/libGLESv2/Program.cpp  |   24 +-
 src/3rdparty/angle/src/libGLESv2/Program.h    |    5 +-
 .../angle/src/libGLESv2/ProgramBinary.cpp     | 2252 +++--------------
 .../angle/src/libGLESv2/ProgramBinary.h       |  133 +-
 .../angle/src/libGLESv2/Renderbuffer.cpp      |  235 +-
 .../angle/src/libGLESv2/Renderbuffer.h        |  113 +-
 .../angle/src/libGLESv2/ResourceManager.cpp   |   16 +-
 .../angle/src/libGLESv2/ResourceManager.h     |    7 +-
 src/3rdparty/angle/src/libGLESv2/Shader.cpp   |   10 +-
 src/3rdparty/angle/src/libGLESv2/Shader.h     |    4 +-
 src/3rdparty/angle/src/libGLESv2/State.cpp    |  125 +-
 src/3rdparty/angle/src/libGLESv2/State.h      |   26 +-
 src/3rdparty/angle/src/libGLESv2/Texture.cpp  |  199 +-
 src/3rdparty/angle/src/libGLESv2/Texture.h    |   74 +-
 .../angle/src/libGLESv2/VertexArray.h         |    5 +-
 .../angle/src/libGLESv2/angletypes.cpp        |   21 +-
 src/3rdparty/angle/src/libGLESv2/angletypes.h |   16 +-
 .../angle/src/libGLESv2/libGLESv2.cpp         | 1045 +++++---
 src/3rdparty/angle/src/libGLESv2/main.cpp     |   99 +-
 src/3rdparty/angle/src/libGLESv2/main.h       |   21 +-
 .../angle/src/libGLESv2/renderer/BufferImpl.h |    3 +-
 .../angle/src/libGLESv2/renderer/FenceImpl.h  |   36 +-
 .../angle/src/libGLESv2/renderer/Image.cpp    |   22 +-
 .../angle/src/libGLESv2/renderer/Image.h      |   25 +-
 .../libGLESv2/renderer/IndexRangeCache.cpp    |    4 -
 .../src/libGLESv2/renderer/ProgramImpl.cpp    |  146 ++
 .../src/libGLESv2/renderer/ProgramImpl.h      |  127 +-
 .../src/libGLESv2/renderer/RenderTarget.cpp   |   36 +
 .../src/libGLESv2/renderer/RenderTarget.h     |   41 +-
 .../libGLESv2/renderer/RenderbufferImpl.cpp   |   21 +
 .../src/libGLESv2/renderer/RenderbufferImpl.h |   41 +
 .../angle/src/libGLESv2/renderer/Renderer.cpp |   45 +-
 .../angle/src/libGLESv2/renderer/Renderer.h   |  237 +-
 .../src/libGLESv2/renderer/ShaderExecutable.h |   13 +-
 .../angle/src/libGLESv2/renderer/ShaderImpl.h |    3 +-
 .../angle/src/libGLESv2/renderer/SwapChain.h  |   25 +-
 .../src/libGLESv2/renderer/TextureImpl.h      |   24 +-
 .../src/libGLESv2/renderer/Workarounds.h      |   39 +
 .../src/libGLESv2/renderer/copyimage.cpp      |    2 +-
 .../src/libGLESv2/renderer/d3d/BufferD3D.cpp  |   12 +-
 .../src/libGLESv2/renderer/d3d/BufferD3D.h    |   17 +-
 .../libGLESv2/renderer/d3d/DynamicHLSL.cpp    |   68 +-
 .../src/libGLESv2/renderer/d3d/DynamicHLSL.h  |   35 +-
 .../libGLESv2/renderer/d3d/HLSLCompiler.cpp   |  245 +-
 .../src/libGLESv2/renderer/d3d/HLSLCompiler.h |   28 +-
 .../src/libGLESv2/renderer/d3d/ImageD3D.cpp   |    4 +-
 .../src/libGLESv2/renderer/d3d/ImageD3D.h     |   15 +-
 .../libGLESv2/renderer/d3d/IndexBuffer.cpp    |    8 +-
 .../src/libGLESv2/renderer/d3d/IndexBuffer.h  |   10 +-
 .../renderer/d3d/IndexDataManager.cpp         |   24 +-
 .../libGLESv2/renderer/d3d/IndexDataManager.h |    6 +-
 .../src/libGLESv2/renderer/d3d/ProgramD3D.cpp | 1942 +++++++++++++-
 .../src/libGLESv2/renderer/d3d/ProgramD3D.h   |  184 +-
 .../renderer/d3d/RenderbufferD3D.cpp          |  108 +
 .../libGLESv2/renderer/d3d/RenderbufferD3D.h  |   51 +
 .../libGLESv2/renderer/d3d/RendererD3D.cpp    |  796 ++++++
 .../src/libGLESv2/renderer/d3d/RendererD3D.h  |  195 ++
 .../src/libGLESv2/renderer/d3d/ShaderD3D.cpp  |  118 +-
 .../src/libGLESv2/renderer/d3d/ShaderD3D.h    |   22 +-
 .../src/libGLESv2/renderer/d3d/TextureD3D.cpp | 1711 ++++++++-----
 .../src/libGLESv2/renderer/d3d/TextureD3D.h   |  227 +-
 .../libGLESv2/renderer/d3d/TextureStorage.cpp |   18 +-
 .../libGLESv2/renderer/d3d/TextureStorage.h   |   21 +-
 .../libGLESv2/renderer/d3d/VertexBuffer.cpp   |   12 +-
 .../src/libGLESv2/renderer/d3d/VertexBuffer.h |   10 +-
 .../renderer/d3d/VertexDataManager.cpp        |   36 +-
 .../renderer/d3d/VertexDataManager.h          |   13 +-
 .../libGLESv2/renderer/d3d/d3d11/Blit11.cpp   |  108 +-
 .../src/libGLESv2/renderer/d3d/d3d11/Blit11.h |   38 +-
 .../libGLESv2/renderer/d3d/d3d11/Buffer11.cpp |   88 +-
 .../libGLESv2/renderer/d3d/d3d11/Buffer11.h   |    8 +-
 .../libGLESv2/renderer/d3d/d3d11/Clear11.cpp  |   19 +-
 .../libGLESv2/renderer/d3d/d3d11/Clear11.h    |    2 +-
 .../libGLESv2/renderer/d3d/d3d11/Fence11.cpp  |  214 +-
 .../libGLESv2/renderer/d3d/d3d11/Fence11.h    |   48 +-
 .../libGLESv2/renderer/d3d/d3d11/Image11.cpp  |  549 ++--
 .../libGLESv2/renderer/d3d/d3d11/Image11.h    |   40 +-
 .../renderer/d3d/d3d11/IndexBuffer11.h        |    2 +-
 .../renderer/d3d/d3d11/InputLayoutCache.cpp   |   14 +-
 .../renderer/d3d/d3d11/PixelTransfer11.cpp    |  116 +-
 .../renderer/d3d/d3d11/PixelTransfer11.h      |   12 +-
 .../libGLESv2/renderer/d3d/d3d11/Query11.cpp  |    3 +-
 .../libGLESv2/renderer/d3d/d3d11/Query11.h    |    4 +-
 .../renderer/d3d/d3d11/RenderStateCache.cpp   |   15 +-
 .../renderer/d3d/d3d11/RenderStateCache.h     |    3 +-
 .../renderer/d3d/d3d11/RenderTarget11.cpp     |  327 +--
 .../renderer/d3d/d3d11/RenderTarget11.h       |   84 +-
 .../renderer/d3d/d3d11/Renderer11.cpp         | 1298 +++++-----
 .../libGLESv2/renderer/d3d/d3d11/Renderer11.h |  152 +-
 .../renderer/d3d/d3d11/SwapChain11.cpp        |  169 +-
 .../renderer/d3d/d3d11/SwapChain11.h          |   10 +-
 .../renderer/d3d/d3d11/TextureStorage11.cpp   | 1821 +++++++------
 .../renderer/d3d/d3d11/TextureStorage11.h     |  177 +-
 .../renderer/d3d/d3d11/VertexArray11.h        |    4 +-
 .../renderer/d3d/d3d11/VertexBuffer11.cpp     |   13 +-
 .../renderer/d3d/d3d11/VertexBuffer11.h       |    4 +-
 .../renderer/d3d/d3d11/formatutils11.cpp      |    2 +-
 .../renderer/d3d/d3d11/renderer11_utils.cpp   |   94 +-
 .../renderer/d3d/d3d11/renderer11_utils.h     |    6 +-
 .../src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp |  227 +-
 .../src/libGLESv2/renderer/d3d/d3d9/Blit9.h   |   32 +-
 .../libGLESv2/renderer/d3d/d3d9/Buffer9.cpp   |   13 +-
 .../src/libGLESv2/renderer/d3d/d3d9/Buffer9.h |    8 +-
 .../libGLESv2/renderer/d3d/d3d9/Fence9.cpp    |   63 +-
 .../src/libGLESv2/renderer/d3d/d3d9/Fence9.h  |   19 +-
 .../libGLESv2/renderer/d3d/d3d9/Image9.cpp    |  654 ++---
 .../src/libGLESv2/renderer/d3d/d3d9/Image9.h  |   43 +-
 .../renderer/d3d/d3d9/IndexBuffer9.h          |    2 +-
 .../libGLESv2/renderer/d3d/d3d9/Query9.cpp    |    2 +-
 .../src/libGLESv2/renderer/d3d/d3d9/Query9.h  |    4 +-
 .../renderer/d3d/d3d9/RenderTarget9.cpp       |  165 +-
 .../renderer/d3d/d3d9/RenderTarget9.h         |   60 +-
 .../libGLESv2/renderer/d3d/d3d9/Renderer9.cpp |  756 +++---
 .../libGLESv2/renderer/d3d/d3d9/Renderer9.h   |  134 +-
 .../libGLESv2/renderer/d3d/d3d9/ShaderCache.h |   12 +-
 .../renderer/d3d/d3d9/SwapChain9.cpp          |   26 +-
 .../libGLESv2/renderer/d3d/d3d9/SwapChain9.h  |    7 +-
 .../renderer/d3d/d3d9/TextureStorage9.cpp     |  377 ++-
 .../renderer/d3d/d3d9/TextureStorage9.h       |   46 +-
 .../renderer/d3d/d3d9/VertexArray9.h          |    4 +-
 .../renderer/d3d/d3d9/VertexBuffer9.cpp       |   16 +-
 .../renderer/d3d/d3d9/VertexBuffer9.h         |    4 +-
 .../renderer/d3d/d3d9/renderer9_utils.cpp     |   28 +-
 .../renderer/d3d/d3d9/renderer9_utils.h       |    5 +-
 .../src/libGLESv2/renderer/loadimageSSE2.cpp  |   18 +-
 .../angle/src/libGLESv2/validationES.cpp      |   66 +-
 .../angle/src/libGLESv2/validationES3.cpp     |   23 +-
 .../src/third_party/systeminfo/SystemInfo.cpp |    5 +
 .../0000-General-fixes-for-ANGLE-2.1.patch    | 1194 +--------
 ...pilation-for-MSVC-2008-and-std-tuple.patch |   31 -
 ...-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch |   33 -
 ...-to-link-ANGLE-statically-for-single.patch |   31 +-
 ...Fix-build-when-SSE2-is-not-available.patch |   84 -
 ...of-libGLESv2-with-older-MinGW-w64-he.patch |   49 -
 ...-with-Microsoft-Visual-Studio-14-CTP.patch |   28 -
 ...y-load-D3D-compiler-from-a-list-or-t.patch |   37 +-
 .../patches/0009-ANGLE-Support-WinRT.patch    | 1769 +++++--------
 ...able-D3D11-for-feature-level-9-cards.patch |  266 +-
 ...0012-ANGLE-fix-semantic-index-lookup.patch |   16 +-
 ...support-for-querying-platform-device.patch |   31 +-
 ...e-multithreaded-devices-if-necessary.patch |   37 +-
 ...15-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch |  309 ++-
 ...GLE-Fix-compilation-with-MinGW-D3D11.patch |  322 +--
 src/angle/src/libEGL/libEGL.pro               |   20 +
 src/angle/src/libGLESv2/libGLESv2.pro         |   26 +-
 231 files changed, 16709 insertions(+), 13422 deletions(-)
 create mode 100644 src/3rdparty/angle/include/angle_windowsstore.h
 create mode 100644 src/3rdparty/angle/src/common/NativeWindow.h
 create mode 100644 src/3rdparty/angle/src/common/features.h
 create mode 100644 src/3rdparty/angle/src/common/win32/NativeWindow.cpp
 create mode 100644 src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
 create mode 100644 src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h
 create mode 100644 src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp
 create mode 100644 src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h
 create mode 100644 src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp
 create mode 100644 src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h
 create mode 100644 src/3rdparty/angle/src/libEGL/AttributeMap.cpp
 create mode 100644 src/3rdparty/angle/src/libEGL/AttributeMap.h
 create mode 100644 src/3rdparty/angle/src/libEGL/Error.cpp
 create mode 100644 src/3rdparty/angle/src/libEGL/Error.h
 create mode 100644 src/3rdparty/angle/src/libGLESv2/Data.cpp
 create mode 100644 src/3rdparty/angle/src/libGLESv2/Data.h
 create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp
 create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp
 create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp
 create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h
 create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h
 create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp
 create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h
 create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
 create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h
 delete mode 100644 src/angle/patches/0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch
 delete mode 100644 src/angle/patches/0002-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch
 delete mode 100644 src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch
 delete mode 100644 src/angle/patches/0006-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch
 delete mode 100644 src/angle/patches/0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch

diff --git a/src/3rdparty/angle/AUTHORS b/src/3rdparty/angle/AUTHORS
index b79bb5d1614..be114bcf68b 100644
--- a/src/3rdparty/angle/AUTHORS
+++ b/src/3rdparty/angle/AUTHORS
@@ -21,10 +21,12 @@ Mozilla Corporation
 Turbulenz
 Klarälvdalens Datakonsult AB
 Microsoft Open Technologies, Inc.
+NVIDIA Corporation
 
 Jacek Caban
 Mark Callow
 Ginn Chen
+Tibor den Ouden
 James Hauxwell
 Sam Hocevar
 Pierre Leveille
diff --git a/src/3rdparty/angle/CONTRIBUTORS b/src/3rdparty/angle/CONTRIBUTORS
index 0cae10a0f6e..94d009f2b3e 100644
--- a/src/3rdparty/angle/CONTRIBUTORS
+++ b/src/3rdparty/angle/CONTRIBUTORS
@@ -78,7 +78,12 @@ Turbulenz
 Ulrik Persson (ddefrostt)
 Mark Banner (standard8mbp)
 David Kilzer
+Jacek Caban
+Tibor den Ouden
 
 Microsoft Open Technologies, Inc.
 Cooper Partin
 Austin Kinross
+
+NVIDIA Corporation
+ Olli Etuaho
diff --git a/src/3rdparty/angle/include/EGL/egl.h b/src/3rdparty/angle/include/EGL/egl.h
index ab2f0cdfbea..12590a0e203 100644
--- a/src/3rdparty/angle/include/EGL/egl.h
+++ b/src/3rdparty/angle/include/EGL/egl.h
@@ -238,7 +238,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
 #ifndef EGL_VERSION_1_5
 #define EGL_VERSION_1_5 1
 typedef void *EGLSync;
-typedef khronos_intptr_t EGLAttrib;
+typedef intptr_t EGLAttrib;
 typedef khronos_utime_nanoseconds_t EGLTime;
 #define EGL_CONTEXT_MAJOR_VERSION         0x3098
 #define EGL_CONTEXT_MINOR_VERSION         0x30FB
diff --git a/src/3rdparty/angle/include/EGL/eglext.h b/src/3rdparty/angle/include/EGL/eglext.h
index 989359b0268..0cc5eec2930 100644
--- a/src/3rdparty/angle/include/EGL/eglext.h
+++ b/src/3rdparty/angle/include/EGL/eglext.h
@@ -59,7 +59,7 @@ extern "C" {
 #ifndef EGL_KHR_cl_event2
 #define EGL_KHR_cl_event2 1
 typedef void *EGLSyncKHR;
-typedef khronos_intptr_t EGLAttribKHR;
+typedef intptr_t EGLAttribKHR;
 typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
 #ifdef EGL_EGLEXT_PROTOTYPES
 EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
@@ -442,20 +442,22 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
 #define EGL_ANGLE_platform_angle 1
 #define EGL_PLATFORM_ANGLE_ANGLE          0x3201
 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE     0x3202
-#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204
+#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205
 #endif /* EGL_ANGLE_platform_angle */
 
 #ifndef EGL_ANGLE_platform_angle_d3d
 #define EGL_ANGLE_platform_angle_d3d 1
-#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3204
-#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205
-#define EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE 0x3206
+#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3206
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207
+#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208
 #endif /* EGL_ANGLE_platform_angle_d3d */
 
 #ifndef EGL_ANGLE_platform_angle_opengl
 #define EGL_ANGLE_platform_angle_opengl 1
-#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3207
-#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x3208
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3209
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A
 #endif /* EGL_ANGLE_platform_angle_opengl */
 
 #ifndef EGL_ARM_pixmap_multisample_discard
diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h
index ea9f5778ee3..2eb3674a0ba 100644
--- a/src/3rdparty/angle/include/EGL/eglplatform.h
+++ b/src/3rdparty/angle/include/EGL/eglplatform.h
@@ -67,23 +67,22 @@
  * implementations.
  */
 
-#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) /* Windows Runtime */
-
-struct IUnknown;
-
-typedef IUnknown *EGLNativeDisplayType;
-typedef void     *EGLNativePixmapType;
-typedef IUnknown *EGLNativeWindowType;
-
-#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN 1
 #endif
 #include <windows.h>
 
-typedef HDC     EGLNativeDisplayType;
 typedef HBITMAP EGLNativePixmapType;
+
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */
+#include <inspectable.h>
+typedef IInspectable* EGLNativeDisplayType;
+typedef IInspectable* EGLNativeWindowType;
+#else
+typedef HDC     EGLNativeDisplayType;
 typedef HWND    EGLNativeWindowType;
+#endif
 
 #elif defined(__WINSCW__) || defined(__SYMBIAN32__)  /* Symbian */
 
diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h
index b7989f5f7ed..647fed6a026 100644
--- a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h
+++ b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h
@@ -27,6 +27,10 @@
 
 #include "KHR/khrplatform.h"
 
+#include <map>
+#include <string>
+#include <vector>
+
 //
 // This is the platform independent interface between an OGL driver
 // and the shading language compiler.
@@ -42,18 +46,17 @@ typedef unsigned int GLenum;
 // Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
 #include "ShaderVars.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 // Version number for shader translation API.
 // It is incremented every time the API changes.
-#define ANGLE_SH_VERSION 130
+#define ANGLE_SH_VERSION 132
 
 typedef enum {
   SH_GLES2_SPEC = 0x8B40,
   SH_WEBGL_SPEC = 0x8B41,
 
+  SH_GLES3_SPEC = 0x8B86,
+  SH_WEBGL2_SPEC = 0x8B87,
+
   // The CSS Shaders spec is a subset of the WebGL spec.
   //
   // In both CSS vertex and fragment shaders, ANGLE:
@@ -85,31 +88,6 @@ typedef enum {
   SH_HLSL11_OUTPUT = 0x8B48
 } ShShaderOutput;
 
-typedef enum {
-  SH_PRECISION_HIGHP     = 0x5001,
-  SH_PRECISION_MEDIUMP   = 0x5002,
-  SH_PRECISION_LOWP      = 0x5003,
-  SH_PRECISION_UNDEFINED = 0
-} ShPrecisionType;
-
-typedef enum {
-  SH_INFO_LOG_LENGTH                = 0x8B84,
-  SH_OBJECT_CODE_LENGTH             = 0x8B88,  // GL_SHADER_SOURCE_LENGTH
-  SH_ACTIVE_UNIFORMS                = 0x8B86,
-  SH_ACTIVE_UNIFORM_MAX_LENGTH      = 0x8B87,
-  SH_ACTIVE_ATTRIBUTES              = 0x8B89,
-  SH_ACTIVE_ATTRIBUTE_MAX_LENGTH    = 0x8B8A,
-  SH_VARYINGS                       = 0x8BBB,
-  SH_VARYING_MAX_LENGTH             = 0x8BBC,
-  SH_MAPPED_NAME_MAX_LENGTH         = 0x6000,
-  SH_NAME_MAX_LENGTH                = 0x6001,
-  SH_HASHED_NAME_MAX_LENGTH         = 0x6002,
-  SH_HASHED_NAMES_COUNT             = 0x6003,
-  SH_SHADER_VERSION                 = 0x6004,
-  SH_RESOURCES_STRING_LENGTH        = 0x6005,
-  SH_OUTPUT_TYPE                    = 0x6006
-} ShShaderInfo;
-
 // Compile options.
 typedef enum {
   SH_VALIDATE                = 0,
@@ -208,14 +186,14 @@ typedef enum {
 //
 // Driver must call this first, once, before doing any other
 // compiler operations.
-// If the function succeeds, the return value is nonzero, else zero.
+// If the function succeeds, the return value is true, else false.
 //
-COMPILER_EXPORT int ShInitialize();
+COMPILER_EXPORT bool ShInitialize();
 //
 // Driver should call this at shutdown.
-// If the function succeeds, the return value is nonzero, else zero.
+// If the function succeeds, the return value is true, else false.
 //
-COMPILER_EXPORT int ShFinalize();
+COMPILER_EXPORT bool ShFinalize();
 
 // The 64 bits hash function. The first parameter is the input string; the
 // second parameter is the string length.
@@ -246,6 +224,12 @@ typedef struct
     int EXT_frag_depth;
     int EXT_shader_texture_lod;
 
+    // Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives
+    // with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate
+    // EXT_draw_buffers by using it in combination with GLES3.0 glDrawBuffers
+    // function. This applies to Tegra K1 devices.
+    int NV_draw_buffers;
+
     // Set to 1 if highp precision is supported in the fragment language.
     // Default is 0.
     int FragmentPrecisionHigh;
@@ -274,8 +258,10 @@ typedef struct
 
 //
 // Initialize built-in resources with minimum expected values.
+// Parameters:
+// resources: The object to initialize. Will be comparable with memcmp.
 //
-COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources);
+COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources *resources);
 
 //
 // ShHandle held by but opaque to the driver.  It is allocated,
@@ -284,18 +270,15 @@ COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources);
 //
 // If handle creation fails, 0 will be returned.
 //
-typedef void* ShHandle;
+typedef void *ShHandle;
 
 //
-// Returns the a concatenated list of the items in ShBuiltInResources as a string.
+// Returns the a concatenated list of the items in ShBuiltInResources as a
+// null-terminated string.
 // This function must be updated whenever ShBuiltInResources is changed.
 // Parameters:
 // handle: Specifies the handle of the compiler to be used.
-// outStringLen: Specifies the size of the buffer, in number of characters. The size
-//               of the buffer required to store the resources string can be obtained
-//               by calling ShGetInfo with SH_RESOURCES_STRING_LENGTH.
-// outStr: Returns a null-terminated string representing all the built-in resources.
-COMPILER_EXPORT void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outStr);
+COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle handle);
 
 //
 // Driver calls these to create and destroy compiler objects.
@@ -313,12 +296,12 @@ COMPILER_EXPORT ShHandle ShConstructCompiler(
     sh::GLenum type,
     ShShaderSpec spec,
     ShShaderOutput output,
-    const ShBuiltInResources* resources);
+    const ShBuiltInResources *resources);
 COMPILER_EXPORT void ShDestruct(ShHandle handle);
 
 //
 // Compiles the given shader source.
-// If the function succeeds, the return value is nonzero, else zero.
+// If the function succeeds, the return value is true, else false.
 // Parameters:
 // handle: Specifies the handle of compiler to be used.
 // shaderStrings: Specifies an array of pointers to null-terminated strings
@@ -340,123 +323,36 @@ COMPILER_EXPORT void ShDestruct(ShHandle handle);
 // SH_VARIABLES: Extracts attributes, uniforms, and varyings.
 //               Can be queried by calling ShGetVariableInfo().
 //
-COMPILER_EXPORT int ShCompile(
+COMPILER_EXPORT bool ShCompile(
     const ShHandle handle,
-    const char* const shaderStrings[],
+    const char * const shaderStrings[],
     size_t numStrings,
-    int compileOptions
-    );
+    int compileOptions);
 
-// Returns a parameter from a compiled shader.
-// Parameters:
-// handle: Specifies the compiler
-// pname: Specifies the parameter to query.
-// The following parameters are defined:
-// SH_INFO_LOG_LENGTH: the number of characters in the information log
-//                     including the null termination character.
-// SH_OBJECT_CODE_LENGTH: the number of characters in the object code
-//                        including the null termination character.
-// SH_ACTIVE_ATTRIBUTES: the number of active attribute variables.
-// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: the length of the longest active attribute
-//                                 variable name including the null
-//                                 termination character.
-// SH_ACTIVE_UNIFORMS: the number of active uniform variables.
-// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform
-//                               variable name including the null
-//                               termination character.
-// SH_VARYINGS: the number of varying variables.
-// SH_VARYING_MAX_LENGTH: the length of the longest varying variable name
-//                        including the null termination character.
-// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including
-//                            the null termination character.
-// SH_NAME_MAX_LENGTH: the max length of a user-defined name including the
-//                     null termination character.
-// SH_HASHED_NAME_MAX_LENGTH: the max length of a hashed name including the
-//                            null termination character.
-// SH_HASHED_NAMES_COUNT: the number of hashed names from the latest compile.
-// SH_SHADER_VERSION: the version of the shader language
-// SH_OUTPUT_TYPE: the currently set language output type
-//
-// params: Requested parameter
-COMPILER_EXPORT void ShGetInfo(const ShHandle handle,
-                               ShShaderInfo pname,
-                               size_t* params);
+// Return the version of the shader language.
+COMPILER_EXPORT int ShGetShaderVersion(const ShHandle handle);
 
-// Returns nul-terminated information log for a compiled shader.
+// Return the currently set language output type.
+COMPILER_EXPORT ShShaderOutput ShGetShaderOutputType(
+    const ShHandle handle);
+
+// Returns null-terminated information log for a compiled shader.
 // Parameters:
 // handle: Specifies the compiler
-// infoLog: Specifies an array of characters that is used to return
-//          the information log. It is assumed that infoLog has enough memory
-//          to accomodate the information log. The size of the buffer required
-//          to store the returned information log can be obtained by calling
-//          ShGetInfo with SH_INFO_LOG_LENGTH.
-COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog);
+COMPILER_EXPORT const std::string &ShGetInfoLog(const ShHandle handle);
 
 // Returns null-terminated object code for a compiled shader.
 // Parameters:
 // handle: Specifies the compiler
-// infoLog: Specifies an array of characters that is used to return
-//          the object code. It is assumed that infoLog has enough memory to
-//          accomodate the object code. The size of the buffer required to
-//          store the returned object code can be obtained by calling
-//          ShGetInfo with SH_OBJECT_CODE_LENGTH.
-COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode);
-
-// Returns information about a shader variable.
-// Parameters:
-// handle: Specifies the compiler
-// variableType: Specifies the variable type; options include
-//               SH_ACTIVE_ATTRIBUTES, SH_ACTIVE_UNIFORMS, SH_VARYINGS.
-// index: Specifies the index of the variable to be queried.
-// length: Returns the number of characters actually written in the string
-//         indicated by name (excluding the null terminator) if a value other
-//         than NULL is passed.
-// size: Returns the size of the variable.
-// type: Returns the data type of the variable.
-// precision: Returns the precision of the variable.
-// staticUse: Returns 1 if the variable is accessed in a statement after
-//            pre-processing, whether or not run-time flow of control will
-//            cause that statement to be executed.
-//            Returns 0 otherwise.
-// name: Returns a null terminated string containing the name of the
-//       variable. It is assumed that name has enough memory to accormodate
-//       the variable name. The size of the buffer required to store the
-//       variable name can be obtained by calling ShGetInfo with
-//       SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_ACTIVE_UNIFORM_MAX_LENGTH,
-//       SH_VARYING_MAX_LENGTH.
-// mappedName: Returns a null terminated string containing the mapped name of
-//             the variable, It is assumed that mappedName has enough memory
-//             (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care about the
-//             mapped name. If the name is not mapped, then name and mappedName
-//             are the same.
-COMPILER_EXPORT void ShGetVariableInfo(const ShHandle handle,
-                                       ShShaderInfo variableType,
-                                       int index,
-                                       size_t* length,
-                                       int* size,
-                                       sh::GLenum* type,
-                                       ShPrecisionType* precision,
-                                       int* staticUse,
-                                       char* name,
-                                       char* mappedName);
-
-// Returns information about a name hashing entry from the latest compile.
+COMPILER_EXPORT const std::string &ShGetObjectCode(const ShHandle handle);
+
+// Returns a (original_name, hash) map containing all the user defined
+// names in the shader, including variable names, function names, struct
+// names, and struct field names.
 // Parameters:
 // handle: Specifies the compiler
-// index: Specifies the index of the name hashing entry to be queried.
-// name: Returns a null terminated string containing the user defined name.
-//       It is assumed that name has enough memory to accomodate the name.
-//       The size of the buffer required to store the user defined name can
-//       be obtained by calling ShGetInfo with SH_NAME_MAX_LENGTH.
-// hashedName: Returns a null terminated string containing the hashed name of
-//             the uniform variable, It is assumed that hashedName has enough
-//             memory to accomodate the name. The size of the buffer required
-//             to store the name can be obtained by calling ShGetInfo with
-//             SH_HASHED_NAME_MAX_LENGTH.
-COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle,
-                                           int index,
-                                           char* name,
-                                           char* hashedName);
+COMPILER_EXPORT const std::map<std::string, std::string> *ShGetNameHashingMap(
+    const ShHandle handle);
 
 // Shader variable inspection.
 // Returns a pointer to a list of variables of the designated type.
@@ -476,17 +372,17 @@ typedef struct
     int size;
 } ShVariableInfo;
 
-// Returns 1 if the passed in variables pack in maxVectors following
+// Returns true if the passed in variables pack in maxVectors following
 // the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
-// Returns 0 otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
+// Returns false otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
 // flag above.
 // Parameters:
 // maxVectors: the available rows of registers.
 // varInfoArray: an array of variable info (types and sizes).
 // varInfoArraySize: the size of the variable array.
-COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits(
+COMPILER_EXPORT bool ShCheckVariablesWithinPackingLimits(
     int maxVectors,
-    ShVariableInfo* varInfoArray,
+    ShVariableInfo *varInfoArray,
     size_t varInfoArraySize);
 
 // Gives the compiler-assigned register for an interface block.
@@ -497,7 +393,7 @@ COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits(
 // interfaceBlockName: Specifies the interface block
 // indexOut: output variable that stores the assigned register
 COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle,
-                                                 const char *interfaceBlockName,
+                                                 const std::string &interfaceBlockName,
                                                  unsigned int *indexOut);
 
 // Gives the compiler-assigned register for uniforms in the default
@@ -509,11 +405,7 @@ COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle,
 // interfaceBlockName: Specifies the uniform
 // indexOut: output variable that stores the assigned register
 COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle,
-                                          const char *uniformName,
+                                          const std::string &uniformName,
                                           unsigned int *indexOut);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif // _COMPILER_INTERFACE_INCLUDED_
diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h
index 9c38647dda6..da21c3e76e8 100644
--- a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h
+++ b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h
@@ -52,6 +52,21 @@ struct COMPILER_EXPORT ShaderVariable
     unsigned int elementCount() const { return std::max(1u, arraySize); }
     bool isStruct() const { return !fields.empty(); }
 
+    // All of the shader's variables are described using nested data
+    // structures. This is needed in order to disambiguate similar looking
+    // types, such as two structs containing the same fields, but in
+    // different orders. "findInfoByMappedName" provides an easy query for
+    // users to dive into the data structure and fetch the unique variable
+    // instance corresponding to a dereferencing chain of the top-level
+    // variable.
+    // Given a mapped name like 'a[0].b.c[0]', return the ShaderVariable
+    // that defines 'c' in |leafVar|, and the original name 'A[0].B.C[0]'
+    // in |originalName|, based on the assumption that |this| defines 'a'.
+    // If no match is found, return false.
+    bool findInfoByMappedName(const std::string &mappedFullName,
+                              const ShaderVariable **leafVar,
+                              std::string* originalFullName) const;
+
     GLenum type;
     GLenum precision;
     std::string name;
@@ -60,6 +75,16 @@ struct COMPILER_EXPORT ShaderVariable
     bool staticUse;
     std::vector<ShaderVariable> fields;
     std::string structName;
+
+  protected:
+    bool isSameVariableAtLinkTime(const ShaderVariable &other,
+                                  bool matchPrecision) const;
+
+    bool operator==(const ShaderVariable &other) const;
+    bool operator!=(const ShaderVariable &other) const
+    {
+        return !operator==(other);
+    }
 };
 
 struct COMPILER_EXPORT Uniform : public ShaderVariable
@@ -68,6 +93,16 @@ struct COMPILER_EXPORT Uniform : public ShaderVariable
     ~Uniform();
     Uniform(const Uniform &other);
     Uniform &operator=(const Uniform &other);
+    bool operator==(const Uniform &other) const;
+    bool operator!=(const Uniform &other) const
+    {
+        return !operator==(other);
+    }
+
+    // Decide whether two uniforms are the same at shader link time,
+    // assuming one from vertex shader and the other from fragment shader.
+    // See GLSL ES Spec 3.00.3, sec 4.3.5.
+    bool isSameUniformAtLinkTime(const Uniform &other) const;
 };
 
 struct COMPILER_EXPORT Attribute : public ShaderVariable
@@ -76,6 +111,11 @@ struct COMPILER_EXPORT Attribute : public ShaderVariable
     ~Attribute();
     Attribute(const Attribute &other);
     Attribute &operator=(const Attribute &other);
+    bool operator==(const Attribute &other) const;
+    bool operator!=(const Attribute &other) const
+    {
+        return !operator==(other);
+    }
 
     int location;
 };
@@ -86,6 +126,18 @@ struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable
     ~InterfaceBlockField();
     InterfaceBlockField(const InterfaceBlockField &other);
     InterfaceBlockField &operator=(const InterfaceBlockField &other);
+    bool operator==(const InterfaceBlockField &other) const;
+    bool operator!=(const InterfaceBlockField &other) const
+    {
+        return !operator==(other);
+    }
+
+    // Decide whether two InterfaceBlock fields are the same at shader
+    // link time, assuming one from vertex shader and the other from
+    // fragment shader.
+    // See GLSL ES Spec 3.00.3, sec 4.3.7.
+    bool isSameInterfaceBlockFieldAtLinkTime(
+        const InterfaceBlockField &other) const;
 
     bool isRowMajorLayout;
 };
@@ -94,8 +146,18 @@ struct COMPILER_EXPORT Varying : public ShaderVariable
 {
     Varying();
     ~Varying();
-    Varying(const Varying &other);
+    Varying(const Varying &otherg);
     Varying &operator=(const Varying &other);
+    bool operator==(const Varying &other) const;
+    bool operator!=(const Varying &other) const
+    {
+        return !operator==(other);
+    }
+
+    // Decide whether two varyings are the same at shader link time,
+    // assuming one from vertex shader and the other from fragment shader.
+    // See GLSL ES Spec 3.00.3, sec 4.3.9.
+    bool isSameVaryingAtLinkTime(const Varying &other) const;
 
     InterpolationType interpolation;
     bool isInvariant;
diff --git a/src/3rdparty/angle/include/angle_windowsstore.h b/src/3rdparty/angle/include/angle_windowsstore.h
new file mode 100644
index 00000000000..53ec93e037d
--- /dev/null
+++ b/src/3rdparty/angle/include/angle_windowsstore.h
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// angle_windowsstore.h:
+
+#ifndef ANGLE_WINDOWSSTORE_H_
+#define ANGLE_WINDOWSSTORE_H_
+
+// The following properties can be set on the CoreApplication to support additional
+// ANGLE configuration options.
+//
+// The Visual Studio sample templates provided with this version of ANGLE have examples
+// of how to set these property values.
+
+//
+// Property: EGLNativeWindowTypeProperty
+// Type: IInspectable
+// Description: Set this property to specify the window type to use for creating a surface.
+//              If this property is missing, surface creation will fail.
+//
+const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty";
+
+//
+// Property: EGLRenderSurfaceSizeProperty
+// Type: Size
+// Description: Set this property to specify a preferred size in pixels of the render surface.
+//              The render surface size width and height must be greater than 0.
+//              If this property is set, then the render surface size is fixed.
+//              If this property is missing, a default behavior will be provided.
+//              The default behavior uses the window size if a CoreWindow is specified or
+//              the size of the SwapChainPanel control if one is specified.
+//
+const wchar_t EGLRenderSurfaceSizeProperty[] = L"EGLRenderSurfaceSizeProperty";
+
+#endif // ANGLE_WINDOWSSTORE_H_
diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h
index a2e761b131a..08fc893c251 100644
--- a/src/3rdparty/angle/src/commit.h
+++ b/src/3rdparty/angle/src/commit.h
@@ -7,6 +7,6 @@
 //   This is a default commit hash header, when git is not available.
 //
 
-#define ANGLE_COMMIT_HASH "abce76206141"
+#define ANGLE_COMMIT_HASH "30d6c255d238"
 #define ANGLE_COMMIT_HASH_SIZE 12
-#define ANGLE_COMMIT_DATE "2014-09-23 19:37:05 +0000"
+#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000"
diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/common/NativeWindow.h
new file mode 100644
index 00000000000..9e93aeacde7
--- /dev/null
+++ b/src/3rdparty/angle/src/common/NativeWindow.h
@@ -0,0 +1,77 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow.h: Defines NativeWindow, a class for managing and
+// performing operations on an EGLNativeWindowType.
+// It is used for HWND (Desktop Windows) and IInspectable objects
+//(Windows Store Applications).
+
+#ifndef COMMON_NATIVEWINDOW_H_
+#define COMMON_NATIVEWINDOW_H_
+
+#include <EGL/eglplatform.h>
+#include "common/debug.h"
+#include "common/platform.h"
+
+// DXGISwapChain and DXGIFactory are typedef'd to specific required
+// types. The HWND NativeWindow implementation requires IDXGISwapChain
+// and IDXGIFactory and the Windows Store NativeWindow
+// implementation requires IDXGISwapChain1 and IDXGIFactory2.
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+typedef IDXGISwapChain1 DXGISwapChain;
+typedef IDXGIFactory2 DXGIFactory;
+
+#include <wrl.h>
+#include <wrl/wrappers/corewrappers.h>
+#include <windows.applicationmodel.core.h>
+#include <memory>
+
+namespace rx
+{
+class InspectableNativeWindow;
+}
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+
+#else
+typedef IDXGISwapChain DXGISwapChain;
+typedef IDXGIFactory DXGIFactory;
+#endif
+
+namespace rx
+{
+
+class NativeWindow
+{
+public:
+    explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display);
+
+    bool initialize();
+    bool getClientRect(LPRECT rect);
+    bool isIconic();
+
+    HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
+                            DXGI_FORMAT format, UINT width, UINT height,
+                            DXGISwapChain** swapChain);
+
+    inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
+    inline EGLNativeDisplayType getNativeDisplay() const { return mDisplay; }
+
+  private:
+    EGLNativeWindowType mWindow;
+    EGLNativeDisplayType mDisplay;
+
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+    std::shared_ptr<InspectableNativeWindow> mImpl;
+#endif
+
+};
+
+bool IsValidEGLNativeWindowType(EGLNativeWindowType window);
+}
+
+#endif // COMMON_NATIVEWINDOW_H_
diff --git a/src/3rdparty/angle/src/common/angleutils.cpp b/src/3rdparty/angle/src/common/angleutils.cpp
index 2673abf30ac..c1367c460a3 100644
--- a/src/3rdparty/angle/src/common/angleutils.cpp
+++ b/src/3rdparty/angle/src/common/angleutils.cpp
@@ -5,26 +5,33 @@
 //
 
 #include "common/angleutils.h"
-
+#include "debug.h"
+#include <stdio.h>
 #include <vector>
 
-std::string FormatString(const char *fmt, va_list vararg)
+size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& outBuffer)
 {
-    static std::vector<char> buffer(512);
-
     // Attempt to just print to the current buffer
-    int len = vsnprintf(&buffer[0], buffer.size(), fmt, vararg);
-    if (len < 0 || static_cast<size_t>(len) >= buffer.size())
+    int len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg);
+    if (len < 0 || static_cast<size_t>(len) >= outBuffer.size())
     {
         // Buffer was not large enough, calculate the required size and resize the buffer
         len = vsnprintf(NULL, 0, fmt, vararg);
-        buffer.resize(len + 1);
+        outBuffer.resize(len + 1);
 
         // Print again
-        vsnprintf(&buffer[0], buffer.size(), fmt, vararg);
+        len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg);
     }
+    ASSERT(len >= 0);
+    return static_cast<size_t>(len);
+}
+
+std::string FormatString(const char *fmt, va_list vararg)
+{
+    static std::vector<char> buffer(512);
 
-    return std::string(buffer.data(), len);
+    size_t len = FormatStringIntoVector(fmt, vararg, buffer);
+    return std::string(&buffer[0], len);
 }
 
 std::string FormatString(const char *fmt, ...)
diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h
index ddbbd5f5010..b343ece5bc5 100644
--- a/src/3rdparty/angle/src/common/angleutils.h
+++ b/src/3rdparty/angle/src/common/angleutils.h
@@ -17,6 +17,7 @@
 #include <set>
 #include <sstream>
 #include <cstdarg>
+#include <vector>
 
 // A macro to disallow the copy constructor and operator= functions
 // This must be used in the private: declarations for a class
@@ -95,6 +96,13 @@ inline void StructZero(T *obj)
     memset(obj, 0, sizeof(T));
 }
 
+template <typename T>
+inline bool IsMaskFlagSet(T mask, T flag)
+{
+    // Handles multibit flags as well
+    return (mask & flag) == flag;
+}
+
 inline const char* MakeStaticString(const std::string &str)
 {
     static std::set<std::string> strings;
@@ -132,9 +140,12 @@ inline std::string Str(int i)
     return strstr.str();
 }
 
+size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& buffer);
+
 std::string FormatString(const char *fmt, va_list vararg);
 std::string FormatString(const char *fmt, ...);
 
+// snprintf is not defined with MSVC prior to to msvc14
 #if defined(_MSC_VER) && _MSC_VER < 1900
 #define snprintf _snprintf
 #endif
diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp
index dcad3275640..5f55ff1e394 100644
--- a/src/3rdparty/angle/src/common/debug.cpp
+++ b/src/3rdparty/angle/src/common/debug.cpp
@@ -17,41 +17,211 @@
 
 namespace gl
 {
-#if defined(ANGLE_ENABLE_PERF)
-typedef void (WINAPI *PerfOutputFunction)(D3DCOLOR, LPCWSTR);
-#else
-typedef void (*PerfOutputFunction)(unsigned int, const wchar_t*);
-#endif
+#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
+// Wraps the D3D9/D3D11 debug annotation functions.
+class DebugAnnotationWrapper
+{
+  public:
+    DebugAnnotationWrapper() { };
+    virtual ~DebugAnnotationWrapper() { };
+    virtual void beginEvent(const std::wstring &eventName) = 0;
+    virtual void endEvent() = 0;
+    virtual void setMarker(const std::wstring &markerName) = 0;
+    virtual bool getStatus() = 0;
+};
 
-static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg)
+#if defined(ANGLE_ENABLE_D3D9)
+class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper
 {
-#if defined(ANGLE_ENABLE_PERF) || defined(ANGLE_ENABLE_TRACE)
-    std::string formattedMessage = FormatString(format, vararg);
+  public:
+    void beginEvent(const std::wstring &eventName)
+    {
+        D3DPERF_BeginEvent(0, eventName.c_str());
+    }
+
+    void endEvent()
+    {
+        D3DPERF_EndEvent();
+    }
+
+    void setMarker(const std::wstring &markerName)
+    {
+        D3DPERF_SetMarker(0, markerName.c_str());
+    }
+
+    bool getStatus()
+    {
+        return !!D3DPERF_GetStatus();
+    }
+};
+#endif // ANGLE_ENABLE_D3D9
+
+#if defined(ANGLE_ENABLE_D3D11)
+class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper
+{
+  public:
+
+    D3D11DebugAnnotationWrapper()
+      : mInitialized(false),
+        mD3d11Module(NULL),
+        mUserDefinedAnnotation(NULL)
+    {
+        // D3D11 devices can't be created during DllMain.
+        // We defer device creation until the object is actually used.
+    }
+
+    ~D3D11DebugAnnotationWrapper()
+    {
+        if (mInitialized)
+        {
+            SafeRelease(mUserDefinedAnnotation);
+            FreeLibrary(mD3d11Module);
+        }
+    }
+
+    virtual void beginEvent(const std::wstring &eventName)
+    {
+        initializeDevice();
+
+        mUserDefinedAnnotation->BeginEvent(eventName.c_str());
+    }
+
+    virtual void endEvent()
+    {
+        initializeDevice();
+
+        mUserDefinedAnnotation->EndEvent();
+    }
+
+    virtual void setMarker(const std::wstring &markerName)
+    {
+        initializeDevice();
+
+        mUserDefinedAnnotation->SetMarker(markerName.c_str());
+    }
+
+    virtual bool getStatus()
+    {
+        // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
+
+#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE)
+        // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture.
+        // This should only be called in DEBUG mode.
+        // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks.
+        IDXGraphicsAnalysis* graphicsAnalysis;
+        DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis));
+        bool underCapture = (graphicsAnalysis != NULL);
+        SafeRelease(graphicsAnalysis);
+        return underCapture;
 #endif
 
-#if defined(ANGLE_ENABLE_PERF)
-    if (perfActive())
+        // Otherwise, we have to return true here.
+        return true;
+    }
+
+  protected:
+
+    void initializeDevice()
     {
-        // The perf function only accepts wide strings, widen the ascii message
-        static std::wstring wideMessage;
-        if (wideMessage.capacity() < formattedMessage.length())
+        if (!mInitialized)
         {
-            wideMessage.reserve(formattedMessage.size());
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+            mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+            ASSERT(mD3d11Module);
+
+            PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
+            ASSERT(D3D11CreateDevice != NULL);
+#endif // !ANGLE_ENABLE_WINDOWS_STORE
+
+            ID3D11Device* device = NULL;
+            ID3D11DeviceContext* context = NULL;
+
+            HRESULT hr = E_FAIL;
+
+            // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device.
+            hr =  D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &context);
+            ASSERT(SUCCEEDED(hr));
+
+            hr = context->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast<void**>(&mUserDefinedAnnotation));
+            ASSERT(SUCCEEDED(hr) && mUserDefinedAnnotation != NULL);
+
+            SafeRelease(device);
+            SafeRelease(context);
+
+            mInitialized = true;
         }
+    }
+
+    bool mInitialized;
+    HMODULE mD3d11Module;
+    ID3DUserDefinedAnnotation* mUserDefinedAnnotation;
+};
+#endif // ANGLE_ENABLE_D3D11
+
+static DebugAnnotationWrapper* g_DebugAnnotationWrapper = NULL;
+
+void InitializeDebugAnnotations()
+{
+#if defined(ANGLE_ENABLE_D3D9)
+    g_DebugAnnotationWrapper = new D3D9DebugAnnotationWrapper();
+#elif defined(ANGLE_ENABLE_D3D11)
+    // If the project uses D3D9 then we can use the D3D9 debug annotations, even with the D3D11 renderer.
+    // However, if D3D9 is unavailable (e.g. in Windows Store), then we use D3D11 debug annotations.
+    // The D3D11 debug annotations are methods on ID3DUserDefinedAnnotation, which is implemented by the DeviceContext.
+    // This doesn't have to be the same DeviceContext that the renderer uses, though.
+    g_DebugAnnotationWrapper = new D3D11DebugAnnotationWrapper();
+#endif
+}
+
+void UninitializeDebugAnnotations()
+{
+    if (g_DebugAnnotationWrapper != NULL)
+    {
+        SafeDelete(g_DebugAnnotationWrapper);
+    }
+}
+
+#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
 
-        wideMessage.assign(formattedMessage.begin(), formattedMessage.end());
+enum DebugTraceOutputType
+{
+   DebugTraceOutputTypeNone,
+   DebugTraceOutputTypeSetMarker,
+   DebugTraceOutputTypeBeginEvent
+};
+
+static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const char *format, va_list vararg)
+{
+#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
+    static std::vector<char> buffer(512);
 
-        perfFunc(0, wideMessage.c_str());
+    if (perfActive())
+    {
+        size_t len = FormatStringIntoVector(format, vararg, buffer);
+        std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len);
+
+        switch (outputType)
+        {
+            case DebugTraceOutputTypeNone:
+                break;
+            case DebugTraceOutputTypeBeginEvent:
+                g_DebugAnnotationWrapper->beginEvent(formattedWideMessage);
+                break;
+            case DebugTraceOutputTypeSetMarker:
+                g_DebugAnnotationWrapper->setMarker(formattedWideMessage);
+                break;
+        }
     }
-#endif // ANGLE_ENABLE_PERF
+#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
 
-#if defined(ANGLE_ENABLE_TRACE)
+#if defined(ANGLE_ENABLE_DEBUG_TRACE)
 #if defined(NDEBUG)
-    if (traceFileDebugOnly)
+    if (traceInDebugOnly)
     {
         return;
     }
 #endif // NDEBUG
+    std::string formattedMessage = FormatString(format, vararg);
 
     static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
     if (file)
@@ -60,25 +230,29 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c
         file.flush();
     }
 
-#endif // ANGLE_ENABLE_TRACE
+#if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
+    OutputDebugStringA(formattedMessage.c_str());
+#endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER
+
+#endif // ANGLE_ENABLE_DEBUG_TRACE
 }
 
-void trace(bool traceFileDebugOnly, const char *format, ...)
+void trace(bool traceInDebugOnly, const char *format, ...)
 {
     va_list vararg;
     va_start(vararg, format);
-#if defined(ANGLE_ENABLE_PERF)
-    output(traceFileDebugOnly, D3DPERF_SetMarker, format, vararg);
+#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
+    output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg);
 #else
-    output(traceFileDebugOnly, NULL, format, vararg);
+    output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg);
 #endif
     va_end(vararg);
 }
 
 bool perfActive()
 {
-#if defined(ANGLE_ENABLE_PERF)
-    static bool active = D3DPERF_GetStatus() != 0;
+#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
+    static bool active = g_DebugAnnotationWrapper->getStatus();
     return active;
 #else
     return false;
@@ -87,26 +261,28 @@ bool perfActive()
 
 ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
 {
-#if defined(ANGLE_ENABLE_PERF)
-#if !defined(ANGLE_ENABLE_TRACE)
+#if !defined(ANGLE_ENABLE_DEBUG_TRACE)
     if (!perfActive())
     {
         return;
     }
-#endif // !ANGLE_ENABLE_TRACE
+#endif // !ANGLE_ENABLE_DEBUG_TRACE
     va_list vararg;
     va_start(vararg, format);
-    output(true, reinterpret_cast<PerfOutputFunction>(D3DPERF_BeginEvent), format, vararg);
+#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
+    output(true, DebugTraceOutputTypeBeginEvent, format, vararg);
+#else
+    output(true, DebugTraceOutputTypeNone, format, vararg);
+#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
     va_end(vararg);
-#endif // ANGLE_ENABLE_PERF
 }
 
 ScopedPerfEventHelper::~ScopedPerfEventHelper()
 {
-#if defined(ANGLE_ENABLE_PERF)
+#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
     if (perfActive())
     {
-        D3DPERF_EndEvent();
+        g_DebugAnnotationWrapper->endEvent();
     }
 #endif
 }
diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h
index bf2bca8f242..c177f513142 100644
--- a/src/3rdparty/angle/src/common/debug.h
+++ b/src/3rdparty/angle/src/common/debug.h
@@ -20,8 +20,8 @@
 
 namespace gl
 {
-    // Outputs text to the debugging log
-    void trace(bool traceFileDebugOnly, const char *format, ...);
+    // Outputs text to the debugging log, or the debugging window
+    void trace(bool traceInDebugOnly, const char *format, ...);
 
     // Returns whether D3DPERF is active.
     bool perfActive();
@@ -36,31 +36,34 @@ namespace gl
       private:
         DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper);
     };
+
+    void InitializeDebugAnnotations();
+    void UninitializeDebugAnnotations();
 }
 
 // A macro to output a trace of a function call and its arguments to the debugging log
-#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF)
+#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
 #define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
 #else
 #define TRACE(message, ...) (void(0))
 #endif
 
 // A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.
-#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF)
+#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
 #define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
 #else
 #define FIXME(message, ...) (void(0))
 #endif
 
 // A macro to output a function call and its arguments to the debugging log, in case of error.
-#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF)
+#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
 #define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
 #else
 #define ERR(message, ...) (void(0))
 #endif
 
 // A macro to log a performance event around a scope.
-#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF)
+#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
 #if defined(_MSC_VER)
 #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__);
 #else
@@ -83,7 +86,7 @@ namespace gl
 #define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable)
 #endif
 
-#ifndef ANGLE_ENABLE_TRACE
+#ifndef ANGLE_ENABLE_DEBUG_TRACE
 #define UNUSED_TRACE_VARIABLE(variable) ((void)variable)
 #else
 #define UNUSED_TRACE_VARIABLE(variable)
@@ -128,7 +131,7 @@ namespace gl
 #endif
 
 // A macro functioning as a compile-time assert to validate constant conditions
-#if defined(_MSC_VER) && _MSC_VER >= 1600
+#if (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__GNUC__) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3))
 #define META_ASSERT_MSG(condition, msg) static_assert(condition, msg)
 #else
 #define META_ASSERT_CONCAT(a, b) a ## b
diff --git a/src/3rdparty/angle/src/common/features.h b/src/3rdparty/angle/src/common/features.h
new file mode 100644
index 00000000000..b49a0ee8526
--- /dev/null
+++ b/src/3rdparty/angle/src/common/features.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#define ANGLE_DISABLED 0
+#define ANGLE_ENABLED 1
+
+// Feature defaults
+
+// Direct3D9EX
+// The "Debug This Pixel..." feature in PIX often fails when using the
+// D3D9Ex interfaces.  In order to get debug pixel to work on a Vista/Win 7
+// machine, define "ANGLE_D3D9EX=0" in your project file.
+#if !defined(ANGLE_D3D9EX)
+#define ANGLE_D3D9EX ANGLE_ENABLED
+#endif
+
+// Vsync
+// ENABLED allows Vsync to be configured at runtime
+// DISABLED disallows Vsync
+#if !defined(ANGLE_VSYNC)
+#define ANGLE_VSYNC ANGLE_ENABLED
+#endif
+
+// Program binary loading
+#if !defined(ANGLE_PROGRAM_BINARY_LOAD)
+#define ANGLE_PROGRAM_BINARY_LOAD ANGLE_ENABLED
+#endif
+
+// Shader debug info
+#if !defined(ANGLE_SHADER_DEBUG_INFO)
+#define ANGLE_SHADER_DEBUG_INFO ANGLE_DISABLED
+#endif
diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h
index 52f2bc1c0e8..a1717892fd6 100644
--- a/src/3rdparty/angle/src/common/mathutil.h
+++ b/src/3rdparty/angle/src/common/mathutil.h
@@ -109,7 +109,7 @@ inline unsigned int unorm(float x)
 
 inline bool supportsSSE2()
 {
-#ifdef ANGLE_PLATFORM_WINDOWS
+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
     static bool checked = false;
     static bool supports = false;
 
@@ -118,7 +118,6 @@ inline bool supportsSSE2()
         return supports;
     }
 
-#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid()
     int info[4];
     __cpuid(info, 0);
 
@@ -128,7 +127,6 @@ inline bool supportsSSE2()
 
         supports = (info[3] >> 26) & 1;
     }
-#endif
 
     checked = true;
 
diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
index b53394f3371..0001e7142e9 100644
--- a/src/3rdparty/angle/src/common/platform.h
+++ b/src/3rdparty/angle/src/common/platform.h
@@ -11,9 +11,6 @@
 
 #if defined(_WIN32) || defined(_WIN64)
 #   define ANGLE_PLATFORM_WINDOWS 1
-#   if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
-#      define ANGLE_PLATFORM_WINRT 1
-#   endif
 #elif defined(__APPLE__)
 #   define ANGLE_PLATFORM_APPLE 1
 #   define ANGLE_PLATFORM_POSIX 1
@@ -37,6 +34,9 @@
 #endif
 
 #ifdef ANGLE_PLATFORM_WINDOWS
+#   if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+#       define ANGLE_ENABLE_WINDOWS_STORE 1
+#   endif
 #   ifndef STRICT
 #       define STRICT 1
 #   endif
@@ -50,7 +50,7 @@
 #   include <windows.h>
 #   include <intrin.h>
 
-#   if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_PERF)
+#   if defined(ANGLE_ENABLE_D3D9)
 #       include <d3d9.h>
 #      if !defined(COMPILER_IMPLEMENTATION)
 #       include <d3dcompiler.h>
@@ -62,13 +62,26 @@
 #       include <d3d10.h>
 #       include <d3d11.h>
 #       include <dxgi.h>
-#      if _MSC_VER >= 1700
+#      if defined(_MSC_VER) && (_MSC_VER >= 1700)
+#       include <d3d11_1.h>
 #       include <dxgi1_2.h>
 #      endif
 #      if !defined(COMPILER_IMPLEMENTATION)
 #       include <d3dcompiler.h>
 #      endif
-#      if defined(__MINGW32__)
+#   endif
+
+#   if defined(ANGLE_ENABLE_WINDOWS_STORE)
+#       include <dxgi1_3.h>
+#       if defined(_DEBUG)
+#          if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
+#           include <DXProgrammableCapture.h>
+#          endif
+#           include <dxgidebug.h>
+#       endif
+#   endif
+
+#  if defined(__MINGW32__) // Missing defines on MinGW
 typedef enum D3D11_MAP_FLAG
 {
     D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L
@@ -78,8 +91,68 @@ typedef struct D3D11_QUERY_DATA_SO_STATISTICS
     UINT64 NumPrimitivesWritten;
     UINT64 PrimitivesStorageNeeded;
 } D3D11_QUERY_DATA_SO_STATISTICS;
-#      endif
-#   endif
+typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)(
+        IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *,
+        UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **);
+#define D3D11_MESSAGE_CATEGORY UINT
+#define D3D11_MESSAGE_SEVERITY UINT
+#define D3D11_MESSAGE_ID UINT
+struct D3D11_MESSAGE;
+typedef struct D3D11_INFO_QUEUE_FILTER_DESC
+{
+    UINT NumCategories;
+    D3D11_MESSAGE_CATEGORY *pCategoryList;
+    UINT NumSeverities;
+    D3D11_MESSAGE_SEVERITY *pSeverityList;
+    UINT NumIDs;
+    D3D11_MESSAGE_ID *pIDList;
+} D3D11_INFO_QUEUE_FILTER_DESC;
+typedef struct D3D11_INFO_QUEUE_FILTER
+{
+    D3D11_INFO_QUEUE_FILTER_DESC AllowList;
+    D3D11_INFO_QUEUE_FILTER_DESC DenyList;
+} D3D11_INFO_QUEUE_FILTER;
+static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 };
+MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown
+{
+public:
+    virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0;
+    virtual void __stdcall ClearStoredMessages() = 0;
+    virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0;
+    virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0;
+    virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0;
+    virtual UINT64 __stdcall GetNumStoredMessages() = 0;
+    virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0;
+    virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0;
+    virtual UINT64 __stdcall GetMessageCountLimit() = 0;
+    virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
+    virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
+    virtual void __stdcall ClearStorageFilter() = 0;
+    virtual HRESULT __stdcall PushEmptyStorageFilter() = 0;
+    virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0;
+    virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
+    virtual void __stdcall PopStorageFilter() = 0;
+    virtual UINT __stdcall GetStorageFilterStackSize() = 0;
+    virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
+    virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
+    virtual void __stdcall ClearRetrievalFilter() = 0;
+    virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0;
+    virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0;
+    virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
+    virtual void __stdcall PopRetrievalFilter() = 0;
+    virtual UINT __stdcall GetRetrievalFilterStackSize() = 0;
+    virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0;
+    virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0;
+    virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0;
+    virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0;
+    virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0;
+    virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0;
+    virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0;
+    virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0;
+    virtual void __stdcall SetMuteDebugOutput(BOOL) = 0;
+    virtual BOOL __stdcall GetMuteDebugOutput() = 0;
+};
+#endif // __MINGW32__
 
 #   undef near
 #   undef far
diff --git a/src/3rdparty/angle/src/common/tls.cpp b/src/3rdparty/angle/src/common/tls.cpp
index c46fab5303e..cb1b32d3258 100644
--- a/src/3rdparty/angle/src/common/tls.cpp
+++ b/src/3rdparty/angle/src/common/tls.cpp
@@ -10,29 +10,50 @@
 
 #include <assert.h>
 
-#if defined(ANGLE_PLATFORM_WINRT)
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
 #include <vector>
-std::vector<void *> *tls = nullptr;
-std::vector<TLSIndex> *freeIndices = nullptr;
+#include <set>
+#include <map>
+#include <mutex>
+
+#include <wrl/client.h>
+#include <wrl/async.h>
+#include <Windows.System.Threading.h>
+
+using namespace std;
+using namespace Windows::Foundation;
+using namespace ABI::Windows::System::Threading;
+
+// Thread local storage for Windows Store support
+typedef vector<void*> ThreadLocalData;
+
+static __declspec(thread) ThreadLocalData* currentThreadData = nullptr;
+static set<ThreadLocalData*> allThreadData;
+static DWORD nextTlsIndex = 0;
+static vector<DWORD> freeTlsIndices;
+
 #endif
 
 TLSIndex CreateTLSIndex()
 {
     TLSIndex index;
 
-#if defined(ANGLE_PLATFORM_WINRT)
-    if (!tls)
-        tls = new std::vector<void *>;
-    if (freeIndices && !freeIndices->empty()) {
-        index = freeIndices->back();
-        freeIndices->pop_back();
-        return index;
-    } else {
-        tls->push_back(nullptr);
-        return tls->size() - 1;
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+    if (!freeTlsIndices.empty())
+    {
+        DWORD result = freeTlsIndices.back();
+        freeTlsIndices.pop_back();
+        index = result;
     }
-#elif defined(ANGLE_PLATFORM_WINDOWS)
+    else
+    {
+        index = nextTlsIndex++;
+    }
+#else
     index = TlsAlloc();
+#endif
+
 #elif defined(ANGLE_PLATFORM_POSIX)
     // Create global pool key
     if ((pthread_key_create(&index, NULL)) != 0)
@@ -53,13 +74,23 @@ bool DestroyTLSIndex(TLSIndex index)
         return false;
     }
 
-#if defined(ANGLE_PLATFORM_WINRT)
-    if (!freeIndices)
-        freeIndices = new std::vector<TLSIndex>;
-    freeIndices->push_back(index);
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+    assert(index < nextTlsIndex);
+    assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), index) == freeTlsIndices.end());
+
+    freeTlsIndices.push_back(index);
+    for (auto threadData : allThreadData)
+    {
+        if (threadData->size() > index)
+        {
+            threadData->at(index) = nullptr;
+        }
+    }
     return true;
-#elif ANGLE_PLATFORM_WINDOWS
+#else
     return (TlsFree(index) == TRUE);
+#endif
 #elif defined(ANGLE_PLATFORM_POSIX)
     return (pthread_key_delete(index) == 0);
 #endif
@@ -73,11 +104,25 @@ bool SetTLSValue(TLSIndex index, void *value)
         return false;
     }
 
-#if defined(ANGLE_PLATFORM_WINRT)
-    tls->at(index) = value;
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+    ThreadLocalData* threadData = currentThreadData;
+    if (!threadData)
+    {
+        threadData = new ThreadLocalData(index + 1, nullptr);
+        allThreadData.insert(threadData);
+        currentThreadData = threadData;
+    }
+    else if (threadData->size() <= index)
+    {
+        threadData->resize(index + 1, nullptr);
+    }
+
+    threadData->at(index) = value;
     return true;
-#elif defined(ANGLE_PLATFORM_WINDOWS)
+#else
     return (TlsSetValue(index, value) == TRUE);
+#endif
 #elif defined(ANGLE_PLATFORM_POSIX)
     return (pthread_setspecific(index, value) == 0);
 #endif
@@ -85,18 +130,26 @@ bool SetTLSValue(TLSIndex index, void *value)
 
 void *GetTLSValue(TLSIndex index)
 {
-#if !defined(ANGLE_PLATFORM_WINRT) // Valid on WinRT, as Alloc handles the index creation
     assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index");
-#endif
     if (index == TLS_INVALID_INDEX)
     {
         return NULL;
     }
 
-#if defined(ANGLE_PLATFORM_WINRT)
-    return tls->at(index);
-#elif defined(ANGLE_PLATFORM_WINDOWS)
+#ifdef ANGLE_PLATFORM_WINDOWS
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+    ThreadLocalData* threadData = currentThreadData;
+    if (threadData && threadData->size() > index)
+    {
+        return threadData->at(index);
+    }
+    else
+    {
+        return nullptr;
+    }
+#else
     return TlsGetValue(index);
+#endif
 #elif defined(ANGLE_PLATFORM_POSIX)
     return pthread_getspecific(index);
 #endif
diff --git a/src/3rdparty/angle/src/common/tls.h b/src/3rdparty/angle/src/common/tls.h
index c40ae1a0614..8a06e92d1ad 100644
--- a/src/3rdparty/angle/src/common/tls.h
+++ b/src/3rdparty/angle/src/common/tls.h
@@ -11,11 +11,15 @@
 
 #include "common/platform.h"
 
-#if defined(ANGLE_PLATFORM_WINRT)
-    typedef size_t TLSIndex;
-#   define TLS_OUT_OF_INDEXES (static_cast<TLSIndex>(-1))
-#   define TLS_INVALID_INDEX TLS_OUT_OF_INDEXES
-#elif defined(ANGLE_PLATFORM_WINDOWS)
+#ifdef ANGLE_PLATFORM_WINDOWS
+
+// TLS does not exist for Windows Store and needs to be emulated
+#   ifdef ANGLE_ENABLE_WINDOWS_STORE
+#       define TLS_OUT_OF_INDEXES -1
+#       ifndef CREATE_SUSPENDED
+#           define CREATE_SUSPENDED 0x00000004
+#       endif
+#   endif
     typedef DWORD TLSIndex;
 #   define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES)
 #elif defined(ANGLE_PLATFORM_POSIX)
@@ -28,6 +32,9 @@
 #   error Unsupported platform.
 #endif
 
+// TODO(kbr): for POSIX platforms this will have to be changed to take
+// in a destructor function pointer, to allow the thread-local storage
+// to be properly deallocated upon thread exit.
 TLSIndex CreateTLSIndex();
 bool DestroyTLSIndex(TLSIndex index);
 
diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp
index 4b8e325d22c..9d797a6612f 100644
--- a/src/3rdparty/angle/src/common/utilities.cpp
+++ b/src/3rdparty/angle/src/common/utilities.cpp
@@ -9,17 +9,16 @@
 #include "common/utilities.h"
 #include "common/mathutil.h"
 #include "common/platform.h"
-#if defined(ANGLE_PLATFORM_WINRT)
-#  include <locale>
-#  include <codecvt>
-#  include <wrl.h>
-#  include <windows.storage.h>
-   using namespace Microsoft::WRL;
-   using namespace ABI::Windows::Storage;
-#endif
 
 #include <set>
 
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+#  include <wrl.h>
+#  include <wrl/wrappers/corewrappers.h>
+#  include <windows.applicationmodel.core.h>
+#  include <windows.graphics.display.h>
+#endif
+
 namespace gl
 {
 
@@ -447,50 +446,10 @@ int VariableSortOrder(GLenum type)
 
 }
 
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
 std::string getTempPath()
 {
-#if defined(ANGLE_PLATFORM_WINRT)
-    static std::string path;
-
-    while (path.empty())
-    {
-        ComPtr<IApplicationDataStatics> factory;
-        Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData);
-        HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory));
-        if (FAILED(result))
-            break;
-
-        ComPtr<IApplicationData> applicationData;
-        result = factory->get_Current(&applicationData);
-        if (FAILED(result))
-            break;
-
-        ComPtr<IStorageFolder> storageFolder;
-        result = applicationData->get_LocalFolder(&storageFolder);
-        if (FAILED(result))
-            break;
-
-        ComPtr<IStorageItem> localFolder;
-        result = storageFolder.As(&localFolder);
-        if (FAILED(result))
-            break;
-
-        HSTRING localFolderPath;
-        result = localFolder->get_Path(&localFolderPath);
-        if (FAILED(result))
-            break;
-
-        std::wstring_convert< std::codecvt_utf8<wchar_t> > converter;
-        path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL));
-        if (path.empty())
-        {
-            UNREACHABLE();
-            break;
-        }
-    }
-
-    return path;
-#elif defined(ANGLE_PLATFORM_WINDOWS)
+#ifdef ANGLE_PLATFORM_WINDOWS
     char path[MAX_PATH];
     DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
     if (pathLen == 0)
@@ -525,3 +484,33 @@ void writeFile(const char* path, const void* content, size_t size)
     fwrite(content, sizeof(char), size, file);
     fclose(file);
 }
+#endif // !ANGLE_ENABLE_WINDOWS_STORE
+
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+
+void Sleep(unsigned long dwMilliseconds)
+{
+    static HANDLE singletonEvent = nullptr;
+    HANDLE sleepEvent = singletonEvent;
+    if (!sleepEvent)
+    {
+        sleepEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
+
+        if (!sleepEvent)
+            return;
+
+        HANDLE previousEvent = InterlockedCompareExchangePointerRelease(&singletonEvent, sleepEvent, nullptr);
+
+        if (previousEvent)
+        {
+            // Back out if multiple threads try to demand create at the same time.
+            CloseHandle(sleepEvent);
+            sleepEvent = previousEvent;
+        }
+    }
+
+    // Emulate sleep by waiting with timeout on an event that is never signalled.
+    WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false);
+}
+
+#endif // ANGLE_ENABLE_WINDOWS_STORE
diff --git a/src/3rdparty/angle/src/common/utilities.h b/src/3rdparty/angle/src/common/utilities.h
index a823184ecdb..2cf6bed176c 100644
--- a/src/3rdparty/angle/src/common/utilities.h
+++ b/src/3rdparty/angle/src/common/utilities.h
@@ -46,7 +46,13 @@ template <typename outT> outT uiround(GLfloat value) { return static_cast<outT>(
 
 }
 
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
 std::string getTempPath();
 void writeFile(const char* path, const void* data, size_t size);
+#endif
+
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+void Sleep(_In_ unsigned long dwMilliseconds);
+#endif
 
 #endif  // LIBGLESV2_UTILITIES_H
diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp
new file mode 100644
index 00000000000..24407472605
--- /dev/null
+++ b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp
@@ -0,0 +1,66 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow.cpp: Handler for managing HWND native window types.
+
+#include "common/NativeWindow.h"
+#include "common/debug.h"
+
+namespace rx
+{
+bool IsValidEGLNativeWindowType(EGLNativeWindowType window)
+{
+    return (IsWindow(window) == TRUE);
+}
+
+NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) : mWindow(window), mDisplay(display)
+{
+}
+
+bool NativeWindow::initialize()
+{ 
+    return true; 
+}
+
+bool NativeWindow::getClientRect(LPRECT rect)
+{
+    return GetClientRect(mWindow, rect) == TRUE;
+}
+
+bool NativeWindow::isIconic()
+{
+    return IsIconic(mWindow) == TRUE;
+}
+
+HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory,
+                                      DXGI_FORMAT format, unsigned int width, unsigned int height,
+                                      DXGISwapChain** swapChain)
+{
+    if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
+    {
+        return E_INVALIDARG;
+    }
+
+    DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
+    swapChainDesc.BufferCount = 1;
+    swapChainDesc.BufferDesc.Format = format;
+    swapChainDesc.BufferDesc.Width = width;
+    swapChainDesc.BufferDesc.Height = height;
+    swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+    swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+    swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
+    swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
+    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+    swapChainDesc.Flags = 0;
+    swapChainDesc.OutputWindow = mWindow;
+    swapChainDesc.SampleDesc.Count = 1;
+    swapChainDesc.SampleDesc.Quality = 0;
+    swapChainDesc.Windowed = TRUE;
+    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+
+    return factory->CreateSwapChain(device, &swapChainDesc, swapChain);
+}
+}
diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
new file mode 100644
index 00000000000..9b65c156258
--- /dev/null
+++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
@@ -0,0 +1,200 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types.
+
+#include <algorithm>
+#include "common/winrt/CoreWindowNativeWindow.h"
+using namespace ABI::Windows::Foundation::Collections;
+
+namespace rx
+{
+
+typedef ITypedEventHandler<ABI::Windows::UI::Core::CoreWindow *, ABI::Windows::UI::Core::WindowSizeChangedEventArgs *> SizeChangedHandler;
+
+CoreWindowNativeWindow::~CoreWindowNativeWindow()
+{
+    unregisterForSizeChangeEvents();
+}
+
+bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet)
+{
+    ComPtr<IPropertySet> props = propertySet;
+    ComPtr<IInspectable> win = window;
+    ComPtr<IInspectable> displayInformation = display;
+    SIZE swapChainSize = {};
+    bool swapChainSizeSpecified = false;
+    HRESULT result = S_OK;
+
+    // IPropertySet is an optional parameter and can be null.
+    // If one is specified, cache as an IMap and read the properties
+    // used for initial host initialization.
+    if (propertySet)
+    {
+        result = props.As(&mPropertyMap);
+        if (SUCCEEDED(result))
+        {
+            // The EGLRenderSurfaceSizeProperty is optional and may be missing.  The IPropertySet
+            // was prevalidated to contain the EGLNativeWindowType before being passed to
+            // this host.
+            result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified);
+        }
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = win.As(&mCoreWindow);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = displayInformation.As(&mDisplayInformation);
+    }
+
+    if (SUCCEEDED(result))
+    {
+#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
+        ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation2> displayInformation2;
+        result = mDisplayInformation.As(&displayInformation2);
+        ASSERT(SUCCEEDED(result));
+
+        result = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor);
+        ASSERT(SUCCEEDED(result));
+#else
+        ABI::Windows::Graphics::Display::ResolutionScale resolutionScale;
+        result = mDisplayInformation->get_ResolutionScale(&resolutionScale);
+        ASSERT(SUCCEEDED(result));
+
+        mScaleFactor = DOUBLE(resolutionScale) / 100.0;
+#endif
+    }
+
+    if (SUCCEEDED(result))
+    {
+        // If a swapchain size is specfied, then the automatic resize
+        // behaviors implemented by the host should be disabled.  The swapchain
+        // will be still be scaled when being rendered to fit the bounds
+        // of the host.
+        // Scaling of the swapchain output occurs automatically because if
+        // the scaling mode setting DXGI_SCALING_STRETCH on the swapchain.
+        if (swapChainSizeSpecified)
+        {
+            mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy };
+            mSupportsSwapChainResize = false;
+        }
+        else
+        {
+            ABI::Windows::Foundation::Rect rect;
+            HRESULT result = mCoreWindow->get_Bounds(&rect);
+            if (SUCCEEDED(result))
+            {
+                LONG width = std::floor(rect.Width * mScaleFactor + 0.5);
+                LONG height = std::floor(rect.Height * mScaleFactor + 0.5);
+                mClientRect = { 0, 0, width, height };
+            }
+        }
+    }
+
+    if (SUCCEEDED(result))
+    {
+        mNewClientRect = mClientRect;
+        mClientRectChanged = false;
+        return registerForSizeChangeEvents();
+    }
+
+    return false;
+}
+
+bool CoreWindowNativeWindow::registerForSizeChangeEvents()
+{
+    HRESULT result = mCoreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &CoreWindowNativeWindow::onSizeChanged).Get(),
+                                                  &mSizeChangedEventToken);
+
+    if (SUCCEEDED(result))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+void CoreWindowNativeWindow::unregisterForSizeChangeEvents()
+{
+    if (mCoreWindow)
+    {
+        (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken);
+    }
+    mSizeChangedEventToken.value = 0;
+}
+
+HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
+{
+    if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
+    {
+        return E_INVALIDARG;
+    }
+
+    DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
+    swapChainDesc.Width = width;
+    swapChainDesc.Height = height;
+    swapChainDesc.Format = format;
+    swapChainDesc.Stereo = FALSE;
+    swapChainDesc.SampleDesc.Count = 1;
+    swapChainDesc.SampleDesc.Quality = 0;
+    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+    swapChainDesc.BufferCount = 2;
+    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+    swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+
+    *swapChain = nullptr;
+
+    ComPtr<IDXGISwapChain1> newSwapChain;
+    HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
+    if (SUCCEEDED(result))
+    {
+
+#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected
+        // Test if swapchain supports resize.  On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED.  On
+        // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed
+        // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations.
+        if (newSwapChain->ResizeBuffers(swapChainDesc.BufferCount, swapChainDesc.Width, swapChainDesc.Height, swapChainDesc.Format, DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) == DXGI_ERROR_UNSUPPORTED)
+        {
+            mSupportsSwapChainResize = false;
+        }
+#endif // (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+
+        result = newSwapChain.CopyTo(swapChain);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        // If automatic swapchain resize behaviors have been disabled, then
+        // unregister for the resize change events.
+        if (mSupportsSwapChainResize == false)
+        {
+            unregisterForSizeChangeEvents();
+        }
+    }
+
+    return result;
+}
+
+// Basically, this shouldn't be used on Phone
+HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e)
+{
+    ABI::Windows::Foundation::Size size;
+    if (SUCCEEDED(e->get_Size(&size)))
+    {
+        SIZE windowSizeInPixels = {
+            std::floor(size.Width * mScaleFactor + 0.5),
+            std::floor(size.Height * mScaleFactor + 0.5)
+        };
+        setNewClientSize(windowSizeInPixels);
+    }
+
+    return S_OK;
+}
+}
diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h
new file mode 100644
index 00000000000..1c5512417d7
--- /dev/null
+++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types.
+
+#ifndef COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
+#define COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
+
+#include "common/winrt/InspectableNativeWindow.h"
+#include <memory>
+#include <windows.graphics.display.h>
+
+namespace rx
+{
+
+class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
+{
+  public:
+    ~CoreWindowNativeWindow();
+
+    bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet);
+    bool registerForSizeChangeEvents();
+    void unregisterForSizeChangeEvents();
+    HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
+
+  private:
+    HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
+
+    ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
+    ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation;
+    ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
+};
+
+}
+
+#endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp
new file mode 100644
index 00000000000..0589f6dce5e
--- /dev/null
+++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp
@@ -0,0 +1,274 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types.
+
+#include "common/winrt/CoreWindowNativeWindow.h"
+#include "common/winrt/SwapChainPanelNativeWindow.h"
+
+namespace rx
+{
+NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display)
+    : mWindow(window), mDisplay(display)
+{
+}
+
+bool NativeWindow::initialize()
+{
+    // If the native window type is a IPropertySet, extract the
+    // EGLNativeWindowType (IInspectable) and initialize the
+    // proper host with this IPropertySet.
+    ComPtr<ABI::Windows::Foundation::Collections::IPropertySet> propertySet;
+    ComPtr<IInspectable> eglNativeWindow;
+    if (IsEGLConfiguredPropertySet(mWindow, &propertySet, &eglNativeWindow))
+    {
+        // A property set was found and the EGLNativeWindowType was
+        // retrieved. The mWindow member of the host to must be updated
+        // to use the EGLNativeWindowType specified in the property set.
+        // mWindow is treated as a raw pointer not an AddRef'd interface, so
+        // the old mWindow does not need a Release() before this assignment.
+        mWindow = eglNativeWindow.Get();
+    }
+
+    ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow;
+    ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
+    if (IsCoreWindow(mWindow, &coreWindow))
+    {
+        mImpl = std::make_shared<CoreWindowNativeWindow>();
+        if (mImpl)
+        {
+            return mImpl->initialize(mWindow, mDisplay, propertySet.Get());
+        }
+    }
+    else if (IsSwapChainPanel(mWindow, &swapChainPanel))
+    {
+        mImpl = std::make_shared<SwapChainPanelNativeWindow>();
+        if (mImpl)
+        {
+            return mImpl->initialize(mWindow, mDisplay, propertySet.Get());
+        }
+    }
+    else
+    {
+        ERR("Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include ICoreWindow, ISwapChainPanel and IPropertySet");
+    }
+
+    return false;
+}
+
+bool NativeWindow::getClientRect(RECT *rect)
+{
+    if (mImpl)
+    {
+        return mImpl->getClientRect(rect);
+    }
+
+    return false;
+}
+
+bool NativeWindow::isIconic()
+{
+    return false;
+}
+
+HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
+{
+    if (mImpl)
+    {
+        return mImpl->createSwapChain(device, factory, format, width, height, swapChain);
+    }
+
+    return E_UNEXPECTED;
+}
+
+bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow)
+{
+    if (!window)
+    {
+        return false;
+    }
+
+    ComPtr<IInspectable> win = window;
+    ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWin;
+    if (SUCCEEDED(win.As(&coreWin)))
+    {
+        if (coreWindow != nullptr)
+        {
+            *coreWindow = coreWin.Detach();
+        }
+        return true;
+    }
+
+    return false;
+}
+
+bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel)
+{
+    if (!window)
+    {
+        return false;
+    }
+
+    ComPtr<IInspectable> win = window;
+    ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> panel;
+    if (SUCCEEDED(win.As(&panel)))
+    {
+        if (swapChainPanel != nullptr)
+        {
+            *swapChainPanel = panel.Detach();
+        }
+        return true;
+    }
+
+    return false;
+}
+
+bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet, IInspectable **eglNativeWindow)
+{
+    if (!window)
+    {
+        return false;
+    }
+
+    ComPtr<IInspectable> props = window;
+    ComPtr<IPropertySet> propSet;
+    ComPtr<IInspectable> nativeWindow;
+    ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> propMap;
+    boolean hasEglNativeWindowPropertyKey = false;
+
+    HRESULT result = props.As(&propSet);
+    if (SUCCEEDED(result))
+    {
+        result = propSet.As(&propMap);
+    }
+
+    // Look for the presence of the EGLNativeWindowType in the property set
+    if (SUCCEEDED(result))
+    {
+        result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEglNativeWindowPropertyKey);
+    }
+
+    // If the IPropertySet does not contain the required EglNativeWindowType key, the property set is
+    // considered invalid.
+    if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey)
+    {
+        ERR("Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid EGLNativeWindowTypeProperty values include ICoreWindow");
+        return false;
+    }
+
+    // The EglNativeWindowType property exists, so retreive the IInspectable that represents the EGLNativeWindowType
+    if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey)
+    {
+        result = propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        if (propertySet != nullptr)
+        {
+            result = propSet.CopyTo(propertySet);
+        }
+    }
+
+    if (SUCCEEDED(result))
+    {
+        if (eglNativeWindow != nullptr)
+        {
+            result = nativeWindow.CopyTo(eglNativeWindow);
+        }
+    }
+
+    if (SUCCEEDED(result))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+// A Valid EGLNativeWindowType IInspectable can only be:
+//
+// ICoreWindow
+// IPropertySet
+// 
+// Anything else will be rejected as an invalid IInspectable.
+bool IsValidEGLNativeWindowType(EGLNativeWindowType window)
+{
+    return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window);
+}
+
+// Attempts to read an optional SIZE property value that is assumed to be in the form of
+// an ABI::Windows::Foundation::Size.  This function validates the Size value before returning 
+// it to the caller.
+//
+// Possible return values are:
+// S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated
+// S_OK, valueExists == false - optional SIZE value was not found
+// E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set.
+//    * Incorrect property type ( must be PropertyType_Size)
+//    * Invalid property value (width/height must be > 0)
+// Additional errors may be returned from IMap or IPropertyValue
+//
+HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists)
+{
+    if (!propertyMap || !propertyName || !value || !valueExists)
+    {
+        return false;
+    }
+
+    // Assume that the value does not exist
+    *valueExists = false;
+    *value = { 0, 0 };
+
+    ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue;
+    ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty;
+    Size sizeValue = { 0, 0 };
+    boolean hasKey = false;
+
+    HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), &hasKey);
+    if (SUCCEEDED(result) && !hasKey)
+    {
+        // Value does not exist, so return S_OK and set the exists parameter to false to indicate
+        // that a the optional property does not exist.
+        *valueExists = false;
+        return S_OK;
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = propertyValue->get_Type(&propertyType);
+    }
+
+    // Check if the expected Size property is of PropertyType_Size type.
+    if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size)
+    {
+        if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0))
+        {
+            // A valid property value exists
+            *value = { static_cast<long>(sizeValue.Width), static_cast<long>(sizeValue.Height) };
+            *valueExists = true;
+            result = S_OK;
+        }
+        else
+        {
+            // An invalid Size property was detected. Width/Height values must > 0
+            result = E_INVALIDARG;
+        }
+    }
+    else
+    {
+        // An invalid property type was detected. Size property must be of PropertyType_Size
+        result = E_INVALIDARG;
+    }
+
+    return result;
+}
+}
diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h
new file mode 100644
index 00000000000..402941a7882
--- /dev/null
+++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// InspectableNativeWindow.h: Host specific implementation interface for
+// managing IInspectable native window types.
+
+#ifndef COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_
+#define COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_
+
+#include "common/platform.h"
+#include "common/NativeWindow.h"
+#include "angle_windowsstore.h"
+
+#include <windows.ui.xaml.h>
+#include <windows.ui.xaml.media.dxinterop.h>
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+
+namespace rx
+{
+class InspectableNativeWindow
+{
+  public:
+    InspectableNativeWindow() :
+        mSupportsSwapChainResize(true),
+        mRequiresSwapChainScaling(false),
+        mClientRectChanged(false),
+        mClientRect({0,0,0,0}),
+        mNewClientRect({0,0,0,0}),
+        mScaleFactor(1.0)
+    {
+        mSizeChangedEventToken.value = 0;
+    }
+    virtual ~InspectableNativeWindow(){}
+
+    virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0;
+    virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0;
+    virtual bool registerForSizeChangeEvents() = 0;
+    virtual void unregisterForSizeChangeEvents() = 0;
+    virtual HRESULT scaleSwapChain(const SIZE& newSize) { return S_OK; }
+
+    bool getClientRect(RECT *rect)
+    {
+        if (mClientRectChanged && mSupportsSwapChainResize)
+        {
+            mClientRect = mNewClientRect;
+            mClientRectChanged = false;
+        }
+
+        *rect = mClientRect;
+
+        return true;
+    }
+
+    void setNewClientSize(const SIZE &newSize)
+    {
+        if (mSupportsSwapChainResize && !mRequiresSwapChainScaling)
+        {
+            mNewClientRect = { 0, 0, newSize.cx, newSize.cy };
+            mClientRectChanged = true;
+        }
+
+        if (mRequiresSwapChainScaling)
+        {
+            scaleSwapChain(newSize);
+        }
+    }
+
+protected:
+    bool mSupportsSwapChainResize;
+    bool mRequiresSwapChainScaling;
+    RECT mClientRect;
+    RECT mNewClientRect;
+    bool mClientRectChanged;
+    DOUBLE mScaleFactor;
+
+    EventRegistrationToken mSizeChangedEventToken;
+};
+
+bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow = nullptr);
+bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel = nullptr);
+bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr);
+HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists);
+}
+#endif // COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_
diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp
new file mode 100644
index 00000000000..268dfbd8f08
--- /dev/null
+++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp
@@ -0,0 +1,226 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types.
+
+#include "common/winrt/SwapChainPanelNativeWindow.h"
+#include <algorithm>
+#include <math.h>
+using namespace ABI::Windows::Foundation::Collections;
+
+namespace rx
+{
+SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow()
+{
+    unregisterForSizeChangeEvents();
+}
+
+bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet)
+{
+    ComPtr<IPropertySet> props = propertySet;
+    ComPtr<IInspectable> win = window;
+    SIZE swapChainSize = {};
+    bool swapChainSizeSpecified = false;
+    HRESULT result = S_OK;
+
+    // IPropertySet is an optional parameter and can be null.
+    // If one is specified, cache as an IMap and read the properties
+    // used for initial host initialization.
+    if (propertySet)
+    {
+        result = props.As(&mPropertyMap);
+        if (SUCCEEDED(result))
+        {
+            // The EGLRenderSurfaceSizeProperty is optional and may be missing.  The IPropertySet
+            // was prevalidated to contain the EGLNativeWindowType before being passed to
+            // this host.
+            result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified);
+        }
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = win.As(&mSwapChainPanel);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        // If a swapchain size is specfied, then the automatic resize
+        // behaviors implemented by the host should be disabled.  The swapchain
+        // will be still be scaled when being rendered to fit the bounds
+        // of the host.
+        // Scaling of the swapchain output needs to be handled by the
+        // host for swapchain panels even though the scaling mode setting
+        // DXGI_SCALING_STRETCH is configured on the swapchain.
+        if (swapChainSizeSpecified)
+        {
+            mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy };
+
+            // Enable host swapchain scaling
+            mRequiresSwapChainScaling = true;
+        }
+        else
+        {
+            result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect);
+        }
+    }
+
+    if (SUCCEEDED(result))
+    {
+        mNewClientRect = mClientRect;
+        mClientRectChanged = false;
+        return registerForSizeChangeEvents();
+    }
+
+    return false;
+}
+
+bool SwapChainPanelNativeWindow::registerForSizeChangeEvents()
+{
+    ComPtr<ABI::Windows::UI::Xaml::ISizeChangedEventHandler> sizeChangedHandler;
+    ComPtr<ABI::Windows::UI::Xaml::IFrameworkElement> frameworkElement;
+    HRESULT result = Microsoft::WRL::MakeAndInitialize<SwapChainPanelSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this());
+
+    if (SUCCEEDED(result))
+    {
+        result = mSwapChainPanel.As(&frameworkElement);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents()
+{
+    ComPtr<ABI::Windows::UI::Xaml::IFrameworkElement> frameworkElement;
+    if (SUCCEEDED(mSwapChainPanel.As(&frameworkElement)))
+    {
+        (void)frameworkElement->remove_SizeChanged(mSizeChangedEventToken);
+    }
+
+    mSizeChangedEventToken.value = 0;
+}
+
+HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
+{
+    if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
+    {
+        return E_INVALIDARG;
+    }
+
+    DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
+    swapChainDesc.Width = width;
+    swapChainDesc.Height = height;
+    swapChainDesc.Format = format;
+    swapChainDesc.Stereo = FALSE;
+    swapChainDesc.SampleDesc.Count = 1;
+    swapChainDesc.SampleDesc.Quality = 0;
+    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+    swapChainDesc.BufferCount = 2;
+    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+    swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+    swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
+
+    *swapChain = nullptr;
+
+    ComPtr<IDXGISwapChain1> newSwapChain;
+    ComPtr<ISwapChainPanelNative> swapChainPanelNative;
+    RECT currentPanelSize = {};
+
+    HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
+
+    if (SUCCEEDED(result))
+    {
+        result = mSwapChainPanel.As(&swapChainPanelNative);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        result = swapChainPanelNative->SetSwapChain(newSwapChain.Get());
+    }
+
+    if (SUCCEEDED(result))
+    {
+        // The swapchain panel host requires an instance of the swapchain set on the SwapChainPanel
+        // to perform the runtime-scale behavior.  This swapchain is cached here because there are
+        // no methods for retreiving the currently configured on from ISwapChainPanelNative.
+        mSwapChain = newSwapChain;
+        result = newSwapChain.CopyTo(swapChain);
+    }
+
+    // If the host is responsible for scaling the output of the swapchain, then
+    // scale it now before returning an instance to the caller.  This is done by
+    // first reading the current size of the swapchain panel, then scaling
+    if (SUCCEEDED(result) && mRequiresSwapChainScaling)
+    {
+        result = GetSwapChainPanelSize(mSwapChainPanel, &currentPanelSize);
+    }
+
+    // Scale the swapchain to fit inside the contents of the panel.
+    if (SUCCEEDED(result) && mRequiresSwapChainScaling)
+    {
+        SIZE currentSize = { currentPanelSize.right, currentPanelSize.bottom };
+        result = scaleSwapChain(currentSize);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        // If automatic swapchain resize behaviors have been disabled, then
+        // unregister for the resize change events.
+        if (mSupportsSwapChainResize == false)
+        {
+            unregisterForSizeChangeEvents();
+        }
+    }
+
+    return result;
+}
+
+HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &newSize)
+{
+    ABI::Windows::Foundation::Size renderScale = { (float)newSize.cx/(float)mClientRect.right, (float)newSize.cy/(float)mClientRect.bottom };
+    // Setup a scale matrix for the swap chain
+    DXGI_MATRIX_3X2_F scaleMatrix = {};
+    scaleMatrix._11 = renderScale.Width;
+    scaleMatrix._22 = renderScale.Height;
+
+    ComPtr<IDXGISwapChain2> swapChain2;
+    HRESULT result = mSwapChain.As(&swapChain2);
+    if (SUCCEEDED(result))
+    {
+        result = swapChain2->SetMatrixTransform(&scaleMatrix);
+    }
+
+    return result;
+}
+
+HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize)
+{
+    ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement;
+    ABI::Windows::Foundation::Size renderSize = { 0, 0 };
+    HRESULT result = swapChainPanel.As(&uiElement);
+    if (SUCCEEDED(result))
+    {
+        result = uiElement->get_RenderSize(&renderSize);
+    }
+
+    if (SUCCEEDED(result))
+    {
+        *windowSize = { 0, 0, lround(renderSize.Width), lround(renderSize.Height) };
+    }
+
+    return result;
+}
+}
diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h
new file mode 100644
index 00000000000..5bbf274e647
--- /dev/null
+++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h
@@ -0,0 +1,79 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types.
+
+#ifndef COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
+#define COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
+
+#include "common/winrt/InspectableNativeWindow.h"
+
+namespace rx
+{
+class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<SwapChainPanelNativeWindow>
+{
+  public:
+    ~SwapChainPanelNativeWindow();
+
+    bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet);
+    bool registerForSizeChangeEvents();
+    void unregisterForSizeChangeEvents();
+    HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
+    HRESULT scaleSwapChain(const SIZE &newSize);
+
+  private:
+    ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel;
+    ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
+    ComPtr<DXGISwapChain> mSwapChain;
+};
+
+[uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)]
+class SwapChainPanelSizeChangedHandler :
+    public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::UI::Xaml::ISizeChangedEventHandler>
+{
+  public:
+    SwapChainPanelSizeChangedHandler() { }
+    HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host)
+    {
+        if (!host)
+        {
+            return E_INVALIDARG;
+        }
+
+        mHost = host;
+        return S_OK;
+    }
+
+    // ISizeChangedEventHandler
+    IFACEMETHOD(Invoke)(IInspectable *sender, ABI::Windows::UI::Xaml::ISizeChangedEventArgs *sizeChangedEventArgs)
+    {
+        std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
+        if (host)
+        {
+            // The size of the ISwapChainPanel control is returned in DIPs.
+            // We are keeping these in dips because the swapchain created for composition
+            // also uses dip units. This keeps dimensions, viewports, etc in the same unit.
+            // XAML Clients of the ISwapChainPanel are required to use dips to define their
+            // layout sizes as well.
+            ABI::Windows::Foundation::Size newSize;
+            HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize);
+            if (SUCCEEDED(result))
+            {
+                SIZE windowSize = { lround(newSize.Width), lround(newSize.Height) };
+                host->setNewClientSize(windowSize);
+            }
+        }
+
+        return S_OK;
+    }
+
+  private:
+    std::weak_ptr<InspectableNativeWindow> mHost;
+};
+
+HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize);
+}
+#endif // COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
index 040b25c6a24..eec0d5e5f05 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
@@ -29,7 +29,8 @@ class DirectiveHandler
     // Handle pragma of form: #pragma name[(value)]
     virtual void handlePragma(const SourceLocation &loc,
                               const std::string &name,
-                              const std::string &value) = 0;
+                              const std::string &value,
+                              bool stdgl) = 0;
 
     virtual void handleExtension(const SourceLocation &loc,
                                  const std::string &name,
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp
index 6434d5cb5c8..7803ee845ab 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp
@@ -38,19 +38,19 @@ enum DirectiveType
 
 DirectiveType getDirective(const pp::Token *token)
 {
-    static const std::string kDirectiveDefine("define");
-    static const std::string kDirectiveUndef("undef");
-    static const std::string kDirectiveIf("if");
-    static const std::string kDirectiveIfdef("ifdef");
-    static const std::string kDirectiveIfndef("ifndef");
-    static const std::string kDirectiveElse("else");
-    static const std::string kDirectiveElif("elif");
-    static const std::string kDirectiveEndif("endif");
-    static const std::string kDirectiveError("error");
-    static const std::string kDirectivePragma("pragma");
-    static const std::string kDirectiveExtension("extension");
-    static const std::string kDirectiveVersion("version");
-    static const std::string kDirectiveLine("line");
+    const char kDirectiveDefine[] = "define";
+    const char kDirectiveUndef[] = "undef";
+    const char kDirectiveIf[] = "if";
+    const char kDirectiveIfdef[] = "ifdef";
+    const char kDirectiveIfndef[] = "ifndef";
+    const char kDirectiveElse[] = "else";
+    const char kDirectiveElif[] = "elif";
+    const char kDirectiveEndif[] = "endif";
+    const char kDirectiveError[] = "error";
+    const char kDirectivePragma[] = "pragma";
+    const char kDirectiveExtension[] = "extension";
+    const char kDirectiveVersion[] = "version";
+    const char kDirectiveLine[] = "line";
 
     if (token->type != pp::Token::IDENTIFIER)
         return DIRECTIVE_NONE;
@@ -155,7 +155,7 @@ class DefinedParser : public Lexer
   protected:
     virtual void lex(Token *token)
     {
-        static const std::string kDefined("defined");
+        const char kDefined[] = "defined";
 
         mLexer->lex(token);
         if (token->type != Token::IDENTIFIER)
@@ -592,6 +592,11 @@ void DirectiveParser::parsePragma(Token *token)
     int state = PRAGMA_NAME;
 
     mTokenizer->lex(token);
+    bool stdgl = token->text == "STDGL";
+    if (stdgl)
+    {
+        mTokenizer->lex(token);
+    }
     while ((token->type != '\n') && (token->type != Token::LAST))
     {
         switch(state++)
@@ -627,7 +632,7 @@ void DirectiveParser::parsePragma(Token *token)
     }
     else if (state > PRAGMA_NAME)  // Do not notify for empty pragma.
     {
-        mDirectiveHandler->handlePragma(token->location, name, value);
+        mDirectiveHandler->handlePragma(token->location, name, value, stdgl);
     }
 }
 
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp
index d7e0c834657..69e2f390693 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp
@@ -194,8 +194,8 @@ bool MacroExpander::expandMacro(const Macro &macro,
 
         if (macro.predefined)
         {
-            static const std::string kLine = "__LINE__";
-            static const std::string kFile = "__FILE__";
+            const char kLine[] = "__LINE__";
+            const char kFile[] = "__FILE__";
 
             assert(replacements->size() == 1);
             Token& repl = replacements->front();
diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
index 368cd2ae4ad..5c62a64d10b 100644
--- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
@@ -29,24 +29,27 @@
 
 bool IsWebGLBasedSpec(ShShaderSpec spec)
 {
-     return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
+    return (spec == SH_WEBGL_SPEC ||
+            spec == SH_CSS_SHADERS_SPEC ||
+            spec == SH_WEBGL2_SPEC);
 }
 
 size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
 {
     // WebGL defines a max token legnth of 256, while ES2 leaves max token
     // size undefined. ES3 defines a max size of 1024 characters.
-    if (IsWebGLBasedSpec(spec))
+    switch (spec)
     {
+      case SH_WEBGL_SPEC:
+      case SH_CSS_SHADERS_SPEC:
         return 256;
-    }
-    else
-    {
+      default:
         return 1024;
     }
 }
 
 namespace {
+
 class TScopedPoolAllocator
 {
   public:
@@ -82,6 +85,24 @@ class TScopedSymbolTableLevel
   private:
     TSymbolTable* mTable;
 };
+
+int MapSpecToShaderVersion(ShShaderSpec spec)
+{
+    switch (spec)
+    {
+      case SH_GLES2_SPEC:
+      case SH_WEBGL_SPEC:
+      case SH_CSS_SHADERS_SPEC:
+        return 100;
+      case SH_GLES3_SPEC:
+      case SH_WEBGL2_SPEC:
+        return 300;
+      default:
+        UNREACHABLE();
+        return 0;
+    }
+}
+
 }  // namespace
 
 TShHandleBase::TShHandleBase()
@@ -178,9 +199,21 @@ bool TCompiler::compile(const char* const shaderStrings[],
         (parseContext.treeRoot != NULL);
 
     shaderVersion = parseContext.getShaderVersion();
+    if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion)
+    {
+        infoSink.info.prefix(EPrefixError);
+        infoSink.info << "unsupported shader version";
+        success = false;
+    }
 
     if (success)
     {
+        mPragma = parseContext.pragma();
+        if (mPragma.stdgl.invariantAll)
+        {
+            symbolTable.setGlobalInvariant();
+        }
+
         TIntermNode* root = parseContext.treeRoot;
         success = intermediate.postProcess(root);
 
@@ -360,7 +393,8 @@ void TCompiler::setResourceString()
               << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
               << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
               << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
-              << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset;
+              << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
+              << ":NV_draw_buffers:" << compileResources.NV_draw_buffers;
 
     builtInResourcesString = strstream.str();
 }
@@ -377,7 +411,6 @@ void TCompiler::clearResults()
     uniforms.clear();
     expandedUniforms.clear();
     varyings.clear();
-    expandedVaryings.clear();
     interfaceBlocks.clear();
 
     builtInFunctionEmulator.Cleanup();
@@ -507,13 +540,12 @@ void TCompiler::collectVariables(TIntermNode* root)
                                  &uniforms,
                                  &varyings,
                                  &interfaceBlocks,
-                                 hashFunction);
+                                 hashFunction,
+                                 symbolTable);
     root->traverse(&collect);
 
-    // For backwards compatiblity with ShGetVariableInfo, expand struct
-    // uniforms and varyings into separate variables for each field.
-    sh::ExpandVariables(uniforms, &expandedUniforms);
-    sh::ExpandVariables(varyings, &expandedVaryings);
+    // This is for enforcePackingRestriction().
+    sh::ExpandUniforms(uniforms, &expandedUniforms);
 }
 
 bool TCompiler::enforcePackingRestrictions()
@@ -581,3 +613,10 @@ const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
 {
     return builtInFunctionEmulator;
 }
+
+void TCompiler::writePragma()
+{
+    TInfoSinkBase &sink = infoSink.obj;
+    if (mPragma.stdgl.invariantAll)
+        sink << "#pragma STDGL invariant(all)\n";
+}
diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h
index ca0c157884f..b6c9d13ed06 100644
--- a/src/3rdparty/angle/src/compiler/translator/Compiler.h
+++ b/src/3rdparty/angle/src/compiler/translator/Compiler.h
@@ -18,6 +18,7 @@
 #include "compiler/translator/ExtensionBehavior.h"
 #include "compiler/translator/HashNames.h"
 #include "compiler/translator/InfoSink.h"
+#include "compiler/translator/Pragma.h"
 #include "compiler/translator/SymbolTable.h"
 #include "compiler/translator/VariableInfo.h"
 #include "third_party/compiler/ArrayBoundsClamper.h"
@@ -71,9 +72,7 @@ class TCompiler : public TShHandleBase
     const std::vector<sh::Attribute> &getAttributes() const { return attributes; }
     const std::vector<sh::Attribute> &getOutputVariables() const { return outputVariables; }
     const std::vector<sh::Uniform> &getUniforms() const { return uniforms; }
-    const std::vector<sh::ShaderVariable> &getExpandedUniforms() const { return expandedUniforms; }
     const std::vector<sh::Varying> &getVaryings() const { return varyings; }
-    const std::vector<sh::ShaderVariable> &getExpandedVaryings() const { return expandedVaryings; }
     const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; }
 
     ShHashFunction64 getHashFunction() const { return hashFunction; }
@@ -81,7 +80,7 @@ class TCompiler : public TShHandleBase
     TSymbolTable& getSymbolTable() { return symbolTable; }
     ShShaderSpec getShaderSpec() const { return shaderSpec; }
     ShShaderOutput getOutputType() const { return outputType; }
-    std::string getBuiltInResourcesString() const { return builtInResourcesString; }
+    const std::string &getBuiltInResourcesString() const { return builtInResourcesString; }
 
     // Get the resources set by InitBuiltInSymbolTable
     const ShBuiltInResources& getResources() const;
@@ -131,6 +130,8 @@ class TCompiler : public TShHandleBase
     bool limitExpressionComplexity(TIntermNode* root);
     // Get built-in extensions with default behavior.
     const TExtensionBehavior& getExtensionBehavior() const;
+    const TPragma& getPragma() const { return mPragma; }
+    void writePragma();
 
     const ArrayBoundsClamper& getArrayBoundsClamper() const;
     ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
@@ -141,7 +142,6 @@ class TCompiler : public TShHandleBase
     std::vector<sh::Uniform> uniforms;
     std::vector<sh::ShaderVariable> expandedUniforms;
     std::vector<sh::Varying> varyings;
-    std::vector<sh::ShaderVariable> expandedVaryings;
     std::vector<sh::InterfaceBlock> interfaceBlocks;
 
   private:
@@ -174,6 +174,8 @@ class TCompiler : public TShHandleBase
     // name hashing.
     ShHashFunction64 hashFunction;
     NameMap nameMap;
+
+    TPragma mPragma;
 };
 
 //
diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp
index 334eb0bfa8b..f98d32b2b7b 100644
--- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp
@@ -14,6 +14,9 @@
 
 namespace sh
 {
+
+// Detect Loop Discontinuity
+
 bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
 {
     mLoopDepth = 0;
@@ -74,6 +77,55 @@ bool containsLoopDiscontinuity(TIntermNode *node)
     return detectLoopDiscontinuity.traverse(node);
 }
 
+// Detect Any Loop
+
+bool DetectAnyLoop::traverse(TIntermNode *node)
+{
+    mHasLoop = false;
+    node->traverse(this);
+    return mHasLoop;
+}
+
+bool DetectAnyLoop::visitLoop(Visit visit, TIntermLoop *loop)
+{
+    mHasLoop = true;
+    return false;
+}
+
+// The following definitions stop all traversal when we have found a loop
+bool DetectAnyLoop::visitBinary(Visit, TIntermBinary *)
+{
+    return !mHasLoop;
+}
+
+bool DetectAnyLoop::visitUnary(Visit, TIntermUnary *)
+{
+    return !mHasLoop;
+}
+
+bool DetectAnyLoop::visitSelection(Visit, TIntermSelection *)
+{
+    return !mHasLoop;
+}
+
+bool DetectAnyLoop::visitAggregate(Visit, TIntermAggregate *)
+{
+    return !mHasLoop;
+}
+
+bool DetectAnyLoop::visitBranch(Visit, TIntermBranch *)
+{
+    return !mHasLoop;
+}
+
+bool containsAnyLoop(TIntermNode *node)
+{
+    DetectAnyLoop detectAnyLoop;
+    return detectAnyLoop.traverse(node);
+}
+
+// Detect Gradient Operation
+
 bool DetectGradientOperation::traverse(TIntermNode *node)
 {
     mGradientOperation = false;
diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h
index 35d66cbc2e5..67e37be3981 100644
--- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h
+++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h
@@ -32,6 +32,25 @@ class DetectLoopDiscontinuity : public TIntermTraverser
 
 bool containsLoopDiscontinuity(TIntermNode *node);
 
+// Checks for the existence of any loop
+class DetectAnyLoop : public TIntermTraverser
+{
+public:
+    bool traverse(TIntermNode *node);
+
+protected:
+    bool visitBinary(Visit, TIntermBinary *);
+    bool visitUnary(Visit, TIntermUnary *);
+    bool visitSelection(Visit, TIntermSelection *);
+    bool visitAggregate(Visit, TIntermAggregate *);
+    bool visitLoop(Visit, TIntermLoop *);
+    bool visitBranch(Visit, TIntermBranch *);
+
+    bool mHasLoop;
+};
+
+bool containsAnyLoop(TIntermNode *node);
+
 // Checks for intrinsic functions which compute gradients
 class DetectGradientOperation : public TIntermTraverser
 {
diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp
index 59d2835f7b7..f67a03aa932 100644
--- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp
@@ -13,10 +13,10 @@
 
 static TBehavior getBehavior(const std::string& str)
 {
-    static const std::string kRequire("require");
-    static const std::string kEnable("enable");
-    static const std::string kDisable("disable");
-    static const std::string kWarn("warn");
+    const char kRequire[] = "require";
+    const char kEnable[] = "enable";
+    const char kDisable[] = "disable";
+    const char kWarn[] = "warn";
 
     if (str == kRequire) return EBhRequire;
     else if (str == kEnable) return EBhEnable;
@@ -46,50 +46,61 @@ void TDirectiveHandler::handleError(const pp::SourceLocation& loc,
 
 void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
                                      const std::string& name,
-                                     const std::string& value)
+                                     const std::string& value,
+                                     bool stdgl)
 {
-    static const std::string kSTDGL("STDGL");
-    static const std::string kOptimize("optimize");
-    static const std::string kDebug("debug");
-    static const std::string kOn("on");
-    static const std::string kOff("off");
-
-    bool invalidValue = false;
-    if (name == kSTDGL)
+    if (stdgl)
     {
+        const char kInvariant[] = "invariant";
+        const char kAll[] = "all";
+
+        if (name == kInvariant && value == kAll)
+            mPragma.stdgl.invariantAll = true;
         // The STDGL pragma is used to reserve pragmas for use by future
-        // revisions of GLSL. Ignore it.
+        // revisions of GLSL.  Do not generate an error on unexpected
+        // name and value.
         return;
     }
-    else if (name == kOptimize)
-    {
-        if (value == kOn) mPragma.optimize = true;
-        else if (value == kOff) mPragma.optimize = false;
-        else invalidValue = true;
-    }
-    else if (name == kDebug)
-    {
-        if (value == kOn) mPragma.debug = true;
-        else if (value == kOff) mPragma.debug = false;
-        else invalidValue = true;
-    }
     else
     {
-        mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);
-        return;
-    }
+        const char kOptimize[] = "optimize";
+        const char kDebug[] = "debug";
+        const char kOn[] = "on";
+        const char kOff[] = "off";
 
-    if (invalidValue)
-      mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
-                             "invalid pragma value", value,
-                             "'on' or 'off' expected");
+        bool invalidValue = false;
+        if (name == kOptimize)
+        {
+            if (value == kOn) mPragma.optimize = true;
+            else if (value == kOff) mPragma.optimize = false;
+            else invalidValue = true;
+        }
+        else if (name == kDebug)
+        {
+            if (value == kOn) mPragma.debug = true;
+            else if (value == kOff) mPragma.debug = false;
+            else invalidValue = true;
+        }
+        else
+        {
+            mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);
+            return;
+        }
+
+        if (invalidValue)
+        {
+            mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+                                   "invalid pragma value", value,
+                                   "'on' or 'off' expected");
+        }
+    }
 }
 
 void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc,
                                         const std::string& name,
                                         const std::string& behavior)
 {
-    static const std::string kExtAll("all");
+    const char kExtAll[] = "all";
 
     TBehavior behaviorVal = getBehavior(behavior);
     if (behaviorVal == EBhUndefined)
diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h
index 69418c277af..0433c3bf898 100644
--- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h
+++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h
@@ -29,7 +29,8 @@ class TDirectiveHandler : public pp::DirectiveHandler
 
     virtual void handlePragma(const pp::SourceLocation& loc,
                               const std::string& name,
-                              const std::string& value);
+                              const std::string& value,
+                              bool stdgl);
 
     virtual void handleExtension(const pp::SourceLocation& loc,
                                  const std::string& name,
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp
index b155545ad2b..aa0f31d1708 100644
--- a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp
@@ -133,6 +133,14 @@ bool CompareStructure(const TType &leftNodeType,
 //
 ////////////////////////////////////////////////////////////////
 
+void TIntermTyped::setTypePreservePrecision(const TType &t)
+{
+    TPrecision precision = getPrecision();
+    mType = t;
+    ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
+    mType.setPrecision(precision);
+}
+
 #define REPLACE_IF_IS(node, type, original, replacement) \
     if (node == original) { \
         node = static_cast<type *>(replacement); \
@@ -237,6 +245,52 @@ void TIntermAggregate::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) con
     }
 }
 
+void TIntermAggregate::setPrecisionFromChildren()
+{
+    if (getBasicType() == EbtBool)
+    {
+        mType.setPrecision(EbpUndefined);
+        return;
+    }
+
+    TPrecision precision = EbpUndefined;
+    TIntermSequence::iterator childIter = mSequence.begin();
+    while (childIter != mSequence.end())
+    {
+        TIntermTyped *typed = (*childIter)->getAsTyped();
+        if (typed)
+            precision = GetHigherPrecision(typed->getPrecision(), precision);
+        ++childIter;
+    }
+    mType.setPrecision(precision);
+}
+
+void TIntermAggregate::setBuiltInFunctionPrecision()
+{
+    // All built-ins returning bool should be handled as ops, not functions.
+    ASSERT(getBasicType() != EbtBool);
+
+    TPrecision precision = EbpUndefined;
+    TIntermSequence::iterator childIter = mSequence.begin();
+    while (childIter != mSequence.end())
+    {
+        TIntermTyped *typed = (*childIter)->getAsTyped();
+        // ESSL spec section 8: texture functions get their precision from the sampler.
+        if (typed && IsSampler(typed->getBasicType()))
+        {
+            precision = typed->getPrecision();
+            break;
+        }
+        ++childIter;
+    }
+    // ESSL 3.0 spec section 8: textureSize always gets highp precision.
+    // All other functions that take a sampler are assumed to be texture functions.
+    if (mName.find("textureSize") == 0)
+        mType.setPrecision(EbpHigh);
+    else
+        mType.setPrecision(precision);
+}
+
 bool TIntermSelection::replaceChildNode(
     TIntermNode *original, TIntermNode *replacement)
 {
@@ -336,6 +390,7 @@ bool TIntermUnary::promote(TInfoSink &)
             return false;
         break;
       case EOpNegative:
+      case EOpPositive:
       case EOpPostIncrement:
       case EOpPostDecrement:
       case EOpPreIncrement:
@@ -1068,6 +1123,27 @@ TIntermTyped *TIntermConstantUnion::fold(
                 }
                 break;
 
+              case EOpPositive:
+                switch (getType().getBasicType())
+                {
+                  case EbtFloat:
+                    tempConstArray[i].setFConst(unionArray[i].getFConst());
+                    break;
+                  case EbtInt:
+                    tempConstArray[i].setIConst(unionArray[i].getIConst());
+                    break;
+                  case EbtUInt:
+                    tempConstArray[i].setUConst(static_cast<unsigned int>(
+                        static_cast<int>(unionArray[i].getUConst())));
+                    break;
+                  default:
+                    infoSink.info.message(
+                        EPrefixInternalError, getLine(),
+                        "Unary operation not folded into constant");
+                    return NULL;
+                }
+                break;
+
               case EOpLogicalNot:
                 // this code is written for possible future use,
                 // will not get executed currently
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h
index ec440da0109..32c70f4671b 100644
--- a/src/3rdparty/angle/src/compiler/translator/IntermNode.h
+++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.h
@@ -45,6 +45,7 @@ enum TOperator
     //
 
     EOpNegative,
+    EOpPositive,
     EOpLogicalNot,
     EOpVectorLogicalNot,
 
@@ -265,6 +266,7 @@ class TIntermTyped : public TIntermNode
     virtual bool hasSideEffects() const = 0;
 
     void setType(const TType &t) { mType = t; }
+    void setTypePreservePrecision(const TType &t);
     const TType &getType() const { return mType; }
     TType *getTypePointer() { return &mType; }
 
@@ -613,6 +615,9 @@ class TIntermAggregate : public TIntermOperator
 
     virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
 
+    void setPrecisionFromChildren();
+    void setBuiltInFunctionPrecision();
+
   protected:
     TIntermAggregate(const TIntermAggregate &); // disallow copy constructor
     TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator
diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp
index ef4f83307cd..e558683c559 100644
--- a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp
@@ -198,6 +198,7 @@ TIntermTyped *TIntermediate::addUnaryMath(
       case EOpPostDecrement:
       case EOpPreDecrement:
       case EOpNegative:
+      case EOpPositive:
         if (child->getType().getBasicType() == EbtStruct ||
             child->getType().isArray())
         {
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
index 6d07cccc04f..ed590967b12 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
@@ -395,6 +395,7 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
     switch (node->getOp())
     {
       case EOpNegative: preString = "(-"; break;
+      case EOpPositive: preString = "(+"; break;
       case EOpVectorLogicalNot: preString = "not("; break;
       case EOpLogicalNot: preString = "(!"; break;
 
@@ -574,7 +575,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
         // Function declaration.
         ASSERT(visit == PreVisit);
         writeVariableType(node->getType());
-        out << " " << hashName(node->getName());
+        out << " " << hashFunctionName(node->getName());
 
         out << "(";
         writeFunctionParameters(*(node->getSequence()));
@@ -649,17 +650,18 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
             mDeclaringVariables = false;
         }
         break;
-      case EOpInvariantDeclaration: {
-            // Invariant declaration.
-            ASSERT(visit == PreVisit);
+      case EOpInvariantDeclaration:
+        // Invariant declaration.
+        ASSERT(visit == PreVisit);
+        {
             const TIntermSequence *sequence = node->getSequence();
             ASSERT(sequence && sequence->size() == 1);
             const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode();
             ASSERT(symbol);
-            out << "invariant " << symbol->getSymbol() << ";";
-            visitChildren = false;
-            break;
+            out << "invariant " << hashVariableName(symbol->getSymbol());
         }
+        visitChildren = false;
+        break;
       case EOpConstructFloat:
         writeTriplet(visit, "float(", NULL, ")");
         break;
@@ -741,7 +743,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
         writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction);
         break;
       case EOpComma:
-        writeTriplet(visit, NULL, ", ", NULL);
+        writeTriplet(visit, "(", ", ", ")");
         break;
 
       case EOpMod:
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
index a5ea71599d2..30bbbff0f5f 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
@@ -135,6 +135,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator)
     mUniqueIndex = 0;
 
     mContainsLoopDiscontinuity = false;
+    mContainsAnyLoop = false;
     mOutputLod0Function = false;
     mInsideDiscontinuousLoop = false;
     mNestedLoopDepth = 0;
@@ -172,6 +173,7 @@ OutputHLSL::~OutputHLSL()
 void OutputHLSL::output()
 {
     mContainsLoopDiscontinuity = mContext.shaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot);
+    mContainsAnyLoop = containsAnyLoop(mContext.treeRoot);
     const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot);
     makeFlaggedStructMaps(flaggedStructs);
 
@@ -320,14 +322,22 @@ void OutputHLSL::header()
 
     if (mUsesDiscardRewriting)
     {
-        out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n";
+        out << "#define ANGLE_USES_DISCARD_REWRITING\n";
     }
 
     if (mUsesNestedBreak)
     {
-        out << "#define ANGLE_USES_NESTED_BREAK" << "\n";
+        out << "#define ANGLE_USES_NESTED_BREAK\n";
     }
 
+    out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n"
+           "#define LOOP [loop]\n"
+           "#define FLATTEN [flatten]\n"
+           "#else\n"
+           "#define LOOP\n"
+           "#define FLATTEN\n"
+           "#endif\n";
+
     if (mContext.shaderType == GL_FRAGMENT_SHADER)
     {
         TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
@@ -1747,6 +1757,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
     switch (node->getOp())
     {
       case EOpNegative:         outputTriplet(visit, "(-", "", ")");         break;
+      case EOpPositive:         outputTriplet(visit, "(+", "", ")");         break;
       case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")");         break;
       case EOpLogicalNot:       outputTriplet(visit, "(!", "", ")");         break;
       case EOpPostIncrement:    outputTriplet(visit, "(", "", "++)");        break;
@@ -1860,15 +1871,20 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
 
                 if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "")   // Variable declaration
                 {
-                    if (!mInsideFunction)
+                    for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++)
                     {
-                        out << "static ";
-                    }
+                        if (isSingleStatement(*sit))
+                        {
+                            mUnfoldShortCircuit->traverse(*sit);
+                        }
 
-                    out << TypeString(variable->getType()) + " ";
+                        if (!mInsideFunction)
+                        {
+                            out << "static ";
+                        }
+
+                        out << TypeString(variable->getType()) + " ";
 
-                    for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++)
-                    {
                         TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
 
                         if (symbol)
@@ -1884,7 +1900,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
 
                         if (*sit != sequence->back())
                         {
-                            out << ", ";
+                            out << ";\n";
                         }
                     }
                 }
@@ -1925,7 +1941,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
       case EOpPrototype:
         if (visit == PreVisit)
         {
-            out << TypeString(node->getType()) << " " << Decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "(");
+            out << TypeString(node->getType()) << " " << Decorate(TFunction::unmangleName(node->getName())) << (mOutputLod0Function ? "Lod0(" : "(");
 
             TIntermSequence *arguments = node->getSequence();
 
@@ -2287,6 +2303,15 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
     {
         mUnfoldShortCircuit->traverse(node->getCondition());
 
+        // D3D errors when there is a gradient operation in a loop in an unflattened if
+        // however flattening all the ifs in branch heavy shaders made D3D error too.
+        // As a temporary workaround we flatten the ifs only if there is at least a loop
+        // present somewhere in the shader.
+        if (mContext.shaderType == GL_FRAGMENT_SHADER && mContainsAnyLoop)
+        {
+            out << "FLATTEN ";
+        }
+
         out << "if (";
 
         node->getCondition()->traverse(this);
@@ -2367,14 +2392,14 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
 
     if (node->getType() == ELoopDoWhile)
     {
-        out << "{do\n";
+        out << "{LOOP do\n";
 
         outputLineDirective(node->getLine().first_line);
         out << "{\n";
     }
     else
     {
-        out << "{for(";
+        out << "{LOOP for(";
 
         if (node->getInit())
         {
@@ -2503,6 +2528,12 @@ bool OutputHLSL::isSingleStatement(TIntermNode *node)
         {
             return false;
         }
+        else if (aggregate->getOp() == EOpDeclaration)
+        {
+            // Declaring multiple comma-separated variables must be considered multiple statements
+            // because each individual declaration has side effects which are visible in the next.
+            return false;
+        }
         else
         {
             for (TIntermSequence::iterator sit = aggregate->getSequence()->begin(); sit != aggregate->getSequence()->end(); sit++)
@@ -2675,7 +2706,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
 
                 // for(int index = initial; index < clampedLimit; index += increment)
 
-                out << "for(";
+                out << "LOOP for(";
                 index->traverse(this);
                 out << " = ";
                 out << initial;
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h
index bec02479bbc..5525e6eaa62 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h
@@ -144,6 +144,7 @@ class OutputHLSL : public TIntermTraverser
     int mUniqueIndex;   // For creating unique names
 
     bool mContainsLoopDiscontinuity;
+    bool mContainsAnyLoop;
     bool mOutputLod0Function;
     bool mInsideDiscontinuousLoop;
     int mNestedLoopDepth;
diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp
index ff0a49667c8..37969b54684 100644
--- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp
@@ -1004,12 +1004,12 @@ void TParseContext::handleExtensionDirective(const TSourceLoc& loc, const char*
     directiveHandler.handleExtension(srcLoc, extName, behavior);
 }
 
-void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value)
+void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value, bool stdgl)
 {
     pp::SourceLocation srcLoc;
     srcLoc.file = loc.first_file;
     srcLoc.line = loc.first_line;
-    directiveHandler.handlePragma(srcLoc, name, value);
+    directiveHandler.handlePragma(srcLoc, name, value, stdgl);
 }
 
 /////////////////////////////////////////////////////////////////////////////////
@@ -1364,11 +1364,18 @@ TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &inv
     {
         error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
         recover();
-
         return NULL;
     }
     else
     {
+        const TString kGlFrontFacing("gl_FrontFacing");
+        if (*identifier == kGlFrontFacing)
+        {
+            error(identifierLoc, "identifier should not be declared as invariant", identifier->c_str());
+            recover();
+            return NULL;
+        }
+        symbolTable.addInvariantVarying(*identifier);
         const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
         ASSERT(variable);
         const TType &type = variable->getType();
diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h
index 1f4cbdeba95..414c475cbbd 100644
--- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h
+++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h
@@ -116,7 +116,7 @@ struct TParseContext {
     bool supportsExtension(const char* extension);
     bool isExtensionEnabled(const char* extension) const;
     void handleExtensionDirective(const TSourceLoc& loc, const char* extName, const char* behavior);
-    void handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value);
+    void handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value, bool stdgl);
 
     bool containsSampler(TType& type);
     bool areAllChildConst(TIntermAggregate* aggrNode);
diff --git a/src/3rdparty/angle/src/compiler/translator/Pragma.h b/src/3rdparty/angle/src/compiler/translator/Pragma.h
index 2f744123b82..4a930a29628 100644
--- a/src/3rdparty/angle/src/compiler/translator/Pragma.h
+++ b/src/3rdparty/angle/src/compiler/translator/Pragma.h
@@ -7,13 +7,23 @@
 #ifndef COMPILER_PRAGMA_H_
 #define COMPILER_PRAGMA_H_
 
-struct TPragma {
+struct TPragma
+{
+    struct STDGL
+    {
+        STDGL() : invariantAll(false) { }
+
+        bool invariantAll;
+    };
+
+
     // By default optimization is turned on and debug is turned off.
     TPragma() : optimize(true), debug(false) { }
     TPragma(bool o, bool d) : optimize(o), debug(d) { }
 
     bool optimize;
     bool debug;
+    STDGL stdgl;
 };
 
 #endif // COMPILER_PRAGMA_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp
index 20ce71605ce..0d6a1d64cfc 100644
--- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp
@@ -37,72 +37,6 @@ bool isInitialized = false;
 // and the shading language compiler.
 //
 
-static bool CheckVariableMaxLengths(const ShHandle handle,
-                                    size_t expectedValue)
-{
-    size_t activeUniformLimit = 0;
-    ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
-    size_t activeAttribLimit = 0;
-    ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
-    size_t varyingLimit = 0;
-    ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit);
-    return (expectedValue == activeUniformLimit &&
-            expectedValue == activeAttribLimit &&
-            expectedValue == varyingLimit);
-}
-
-bool CheckMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
-{
-    size_t mappedNameMaxLength = 0;
-    ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
-    return (expectedValue == mappedNameMaxLength);
-}
-
-template <typename VarT>
-const sh::ShaderVariable *ReturnVariable(const std::vector<VarT> &infoList, int index)
-{
-    if (index < 0 || static_cast<size_t>(index) >= infoList.size())
-    {
-        return NULL;
-    }
-
-    return &infoList[index];
-}
-
-const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index)
-{
-    switch (varType)
-    {
-      case SH_ACTIVE_ATTRIBUTES:
-        return ReturnVariable(compiler->getAttributes(), index);
-      case SH_ACTIVE_UNIFORMS:
-        return ReturnVariable(compiler->getExpandedUniforms(), index);
-      case SH_VARYINGS:
-        return ReturnVariable(compiler->getExpandedVaryings(), index);
-      default:
-        UNREACHABLE();
-        return NULL;
-    }
-}
-
-ShPrecisionType ConvertPrecision(sh::GLenum precision)
-{
-    switch (precision)
-    {
-      case GL_HIGH_FLOAT:
-      case GL_HIGH_INT:
-        return SH_PRECISION_HIGHP;
-      case GL_MEDIUM_FLOAT:
-      case GL_MEDIUM_INT:
-        return SH_PRECISION_MEDIUMP;
-      case GL_LOW_FLOAT:
-      case GL_LOW_INT:
-        return SH_PRECISION_LOWP;
-      default:
-        return SH_PRECISION_UNDEFINED;
-    }
-}
-
 template <typename VarT>
 const std::vector<VarT> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType);
 
@@ -150,32 +84,48 @@ const std::vector<VarT> *GetShaderVariables(const ShHandle handle, ShaderVariabl
     return GetVariableList<VarT>(compiler, variableType);
 }
 
+TCompiler *GetCompilerFromHandle(ShHandle handle)
+{
+    if (!handle)
+        return NULL;
+    TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+    return base->getAsCompiler();
 }
 
+TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle)
+{
+    if (!handle)
+        return NULL;
+    TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+    return base->getAsTranslatorHLSL();
+}
+
+}  // namespace anonymous
+
 //
 // Driver must call this first, once, before doing any other compiler operations.
 // Subsequent calls to this function are no-op.
 //
-int ShInitialize()
+bool ShInitialize()
 {
     if (!isInitialized)
     {
         isInitialized = InitProcess();
     }
-    return isInitialized ? 1 : 0;
+    return isInitialized;
 }
 
 //
 // Cleanup symbol tables
 //
-int ShFinalize()
+bool ShFinalize()
 {
     if (isInitialized)
     {
         DetachProcess();
         isInitialized = false;
     }
-    return 1;
+    return true;
 }
 
 //
@@ -183,6 +133,9 @@ int ShFinalize()
 //
 void ShInitBuiltInResources(ShBuiltInResources* resources)
 {
+    // Make comparable.
+    memset(resources, 0, sizeof(*resources));
+
     // Constants.
     resources->MaxVertexAttribs = 8;
     resources->MaxVertexUniformVectors = 128;
@@ -201,6 +154,8 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
     resources->EXT_frag_depth = 0;
     resources->EXT_shader_texture_lod = 0;
 
+    resources->NV_draw_buffers = 0;
+
     // Disable highp precision in fragment shader by default.
     resources->FragmentPrecisionHigh = 0;
 
@@ -251,23 +206,13 @@ void ShDestruct(ShHandle handle)
         DeleteCompiler(base->getAsCompiler());
 }
 
-void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outString)
+const std::string &ShGetBuiltInResourcesString(const ShHandle handle)
 {
-    if (!handle || !outString)
-    {
-        return;
-    }
-
-    TShHandleBase *base = static_cast<TShHandleBase*>(handle);
-    TCompiler *compiler = base->getAsCompiler();
-    if (!compiler)
-    {
-        return;
-    }
-
-    strncpy(outString, compiler->getBuiltInResourcesString().c_str(), outStringLen);
-    outString[outStringLen - 1] = '\0';
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
+    return compiler->getBuiltInResourcesString();
 }
+
 //
 // Do an actual compile on the given strings.  The result is left
 // in the given compile object.
@@ -275,219 +220,62 @@ void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, cha
 // Return:  The return value of ShCompile is really boolean, indicating
 // success or failure.
 //
-int ShCompile(
+bool ShCompile(
     const ShHandle handle,
-    const char* const shaderStrings[],
+    const char *const shaderStrings[],
     size_t numStrings,
     int compileOptions)
 {
-    if (handle == 0)
-        return 0;
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
 
-    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
-    TCompiler* compiler = base->getAsCompiler();
-    if (compiler == 0)
-        return 0;
-
-    bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
-    return success ? 1 : 0;
+    return compiler->compile(shaderStrings, numStrings, compileOptions);
 }
 
-void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
+int ShGetShaderVersion(const ShHandle handle)
 {
-    if (!handle || !params)
-        return;
-
-    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
-    TCompiler* compiler = base->getAsCompiler();
-    if (!compiler) return;
+    TCompiler* compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
+    return compiler->getShaderVersion();
+}
 
-    switch(pname)
-    {
-    case SH_INFO_LOG_LENGTH:
-        *params = compiler->getInfoSink().info.size() + 1;
-        break;
-    case SH_OBJECT_CODE_LENGTH:
-        *params = compiler->getInfoSink().obj.size() + 1;
-        break;
-    case SH_ACTIVE_UNIFORMS:
-        *params = compiler->getExpandedUniforms().size();
-        break;
-    case SH_ACTIVE_UNIFORM_MAX_LENGTH:
-        *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
-        break;
-    case SH_ACTIVE_ATTRIBUTES:
-        *params = compiler->getAttributes().size();
-        break;
-    case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
-        *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
-        break;
-    case SH_VARYINGS:
-        *params = compiler->getExpandedVaryings().size();
-        break;
-    case SH_VARYING_MAX_LENGTH:
-        *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
-        break;
-    case SH_MAPPED_NAME_MAX_LENGTH:
-        // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
-        // handle array and struct dereferences.
-        *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
-        break;
-    case SH_NAME_MAX_LENGTH:
-        *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
-        break;
-    case SH_HASHED_NAME_MAX_LENGTH:
-        if (compiler->getHashFunction() == NULL) {
-            *params = 0;
-        } else {
-            // 64 bits hashing output requires 16 bytes for hex 
-            // representation.
-            const char HashedNamePrefix[] = HASHED_NAME_PREFIX;
-            (void)HashedNamePrefix;
-            *params = 16 + sizeof(HashedNamePrefix);
-        }
-        break;
-    case SH_HASHED_NAMES_COUNT:
-        *params = compiler->getNameMap().size();
-        break;
-    case SH_SHADER_VERSION:
-        *params = compiler->getShaderVersion();
-        break;
-    case SH_RESOURCES_STRING_LENGTH:
-        *params = compiler->getBuiltInResourcesString().length() + 1;
-        break;
-    case SH_OUTPUT_TYPE:
-        *params = compiler->getOutputType();
-        break;
-    default: UNREACHABLE();
-    }
+ShShaderOutput ShGetShaderOutputType(const ShHandle handle)
+{
+    TCompiler* compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
+    return compiler->getOutputType();
 }
 
 //
 // Return any compiler log of messages for the application.
 //
-void ShGetInfoLog(const ShHandle handle, char* infoLog)
+const std::string &ShGetInfoLog(const ShHandle handle)
 {
-    if (!handle || !infoLog)
-        return;
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
 
-    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
-    TCompiler* compiler = base->getAsCompiler();
-    if (!compiler) return;
-
-    TInfoSink& infoSink = compiler->getInfoSink();
-    strcpy(infoLog, infoSink.info.c_str());
+    TInfoSink &infoSink = compiler->getInfoSink();
+    return infoSink.info.str();
 }
 
 //
 // Return any object code.
 //
-void ShGetObjectCode(const ShHandle handle, char* objCode)
+const std::string &ShGetObjectCode(const ShHandle handle)
 {
-    if (!handle || !objCode)
-        return;
-
-    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
-    TCompiler* compiler = base->getAsCompiler();
-    if (!compiler) return;
-
-    TInfoSink& infoSink = compiler->getInfoSink();
-    strcpy(objCode, infoSink.obj.c_str());
-}
-
-void ShGetVariableInfo(const ShHandle handle,
-                       ShShaderInfo varType,
-                       int index,
-                       size_t* length,
-                       int* size,
-                       sh::GLenum* type,
-                       ShPrecisionType* precision,
-                       int* staticUse,
-                       char* name,
-                       char* mappedName)
-{
-    if (!handle || !size || !type || !precision || !staticUse || !name)
-        return;
-    ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
-           (varType == SH_ACTIVE_UNIFORMS) ||
-           (varType == SH_VARYINGS));
-
-    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
-    TCompiler* compiler = base->getAsCompiler();
-    if (compiler == 0)
-        return;
-
-    const sh::ShaderVariable *varInfo = GetVariable(compiler, varType, index);
-    if (!varInfo)
-    {
-        return;
-    }
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
 
-    if (length) *length = varInfo->name.size();
-    *size = varInfo->elementCount();
-    *type = varInfo->type;
-    *precision = ConvertPrecision(varInfo->precision);
-    *staticUse = varInfo->staticUse ? 1 : 0;
-
-    // This size must match that queried by
-    // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH
-    // in ShGetInfo, below.
-    size_t variableLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
-    ASSERT(CheckVariableMaxLengths(handle, variableLength));
-    strncpy(name, varInfo->name.c_str(), variableLength);
-    name[variableLength - 1] = 0;
-    if (mappedName)
-    {
-        // This size must match that queried by
-        // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
-        size_t maxMappedNameLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
-        ASSERT(CheckMappedNameMaxLength(handle, maxMappedNameLength));
-        strncpy(mappedName, varInfo->mappedName.c_str(), maxMappedNameLength);
-        mappedName[maxMappedNameLength - 1] = 0;
-    }
+    TInfoSink &infoSink = compiler->getInfoSink();
+    return infoSink.obj.str();
 }
 
-void ShGetNameHashingEntry(const ShHandle handle,
-                           int index,
-                           char* name,
-                           char* hashedName)
+const std::map<std::string, std::string> *ShGetNameHashingMap(
+    const ShHandle handle)
 {
-    if (!handle || !name || !hashedName || index < 0)
-        return;
-
-    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
-    TCompiler* compiler = base->getAsCompiler();
-    if (!compiler) return;
-
-    const NameMap& nameMap = compiler->getNameMap();
-    if (index >= static_cast<int>(nameMap.size()))
-        return;
-
-    NameMap::const_iterator it = nameMap.begin();
-    for (int i = 0; i < index; ++i)
-        ++it;
-
-    size_t len = it->first.length() + 1;
-    size_t max_len = 0;
-    ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len);
-    if (len > max_len) {
-        ASSERT(false);
-        len = max_len;
-    }
-    strncpy(name, it->first.c_str(), len);
-    // To be on the safe side in case the source is longer than expected.
-    name[len - 1] = '\0';
-
-    len = it->second.length() + 1;
-    max_len = 0;
-    ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len);
-    if (len > max_len) {
-        ASSERT(false);
-        len = max_len;
-    }
-    strncpy(hashedName, it->second.c_str(), len);
-    // To be on the safe side in case the source is longer than expected.
-    hashedName[len - 1] = '\0';
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    ASSERT(compiler);
+    return &(compiler->getNameMap());
 }
 
 const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle)
@@ -515,11 +303,11 @@ const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handl
     return GetShaderVariables<sh::InterfaceBlock>(handle, SHADERVAR_INTERFACEBLOCK);
 }
 
-int ShCheckVariablesWithinPackingLimits(
-    int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize)
+bool ShCheckVariablesWithinPackingLimits(
+    int maxVectors, ShVariableInfo *varInfoArray, size_t varInfoArraySize)
 {
     if (varInfoArraySize == 0)
-        return 1;
+        return true;
     ASSERT(varInfoArray);
     std::vector<sh::ShaderVariable> variables;
     for (size_t ii = 0; ii < varInfoArraySize; ++ii)
@@ -528,24 +316,17 @@ int ShCheckVariablesWithinPackingLimits(
         variables.push_back(var);
     }
     VariablePacker packer;
-    return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0;
+    return packer.CheckVariablesWithinPackingLimits(maxVectors, variables);
 }
 
 bool ShGetInterfaceBlockRegister(const ShHandle handle,
-                                 const char *interfaceBlockName,
+                                 const std::string &interfaceBlockName,
                                  unsigned int *indexOut)
 {
-    if (!handle || !interfaceBlockName || !indexOut)
-    {
-        return false;
-    }
+    ASSERT(indexOut);
 
-    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
-    TranslatorHLSL* translator = base->getAsTranslatorHLSL();
-    if (!translator)
-    {
-        return false;
-    }
+    TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
+    ASSERT(translator);
 
     if (!translator->hasInterfaceBlock(interfaceBlockName))
     {
@@ -557,20 +338,12 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle,
 }
 
 bool ShGetUniformRegister(const ShHandle handle,
-                          const char *uniformName,
+                          const std::string &uniformName,
                           unsigned int *indexOut)
 {
-    if (!handle || !uniformName || !indexOut)
-    {
-        return false;
-    }
-
-    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
-    TranslatorHLSL* translator = base->getAsTranslatorHLSL();
-    if (!translator)
-    {
-        return false;
-    }
+    ASSERT(indexOut);
+    TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
+    ASSERT(translator);
 
     if (!translator->hasUniform(uniformName))
     {
diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp
index 822c558c9bd..3098a7f0c95 100644
--- a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp
@@ -9,6 +9,8 @@
 
 #include <GLSLANG/ShaderLang.h>
 
+#include "compiler/translator/compilerdebug.h"
+
 namespace sh
 {
 
@@ -53,6 +55,126 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
     return *this;
 }
 
+bool ShaderVariable::operator==(const ShaderVariable &other) const
+{
+    if (type != other.type ||
+        precision != other.precision ||
+        name != other.name ||
+        mappedName != other.mappedName ||
+        arraySize != other.arraySize ||
+        staticUse != other.staticUse ||
+        fields.size() != other.fields.size() ||
+        structName != other.structName)
+    {
+        return false;
+    }
+    for (size_t ii = 0; ii < fields.size(); ++ii)
+    {
+        if (fields[ii] != other.fields[ii])
+            return false;
+    }
+    return true;
+}
+
+bool ShaderVariable::findInfoByMappedName(
+    const std::string &mappedFullName,
+    const ShaderVariable **leafVar, std::string *originalFullName) const
+{
+    ASSERT(leafVar && originalFullName);
+    // There are three cases:
+    // 1) the top variable is of struct type;
+    // 2) the top variable is an array;
+    // 3) otherwise.
+    size_t pos = mappedFullName.find_first_of(".[");
+    std::string topName;
+
+    if (pos == std::string::npos)
+    {
+        // Case 3.
+        if (mappedFullName != this->mappedName)
+            return false;
+        *originalFullName = this->name;
+        *leafVar = this;
+        return true;
+    }
+    else
+    {
+        std::string topName = mappedFullName.substr(0, pos);
+        if (topName != this->mappedName)
+            return false;
+        std::string originalName = this->name;
+        std::string remaining;
+        if (mappedFullName[pos] == '[')
+        {
+            // Case 2.
+            size_t closePos = mappedFullName.find_first_of(']');
+            if (closePos < pos || closePos == std::string::npos)
+                return false;
+            // Append '[index]'.
+            originalName += mappedFullName.substr(pos, closePos - pos + 1);
+            if (closePos + 1 == mappedFullName.size())
+            {
+                *originalFullName = originalName;
+                *leafVar = this;
+                return true;
+            }
+            else
+            {
+                // In the form of 'a[0].b', so after ']', '.' is expected.
+                if (mappedFullName[closePos + 1]  != '.')
+                    return false;
+                remaining = mappedFullName.substr(closePos + 2);  // Skip "]."
+            }
+        }
+        else
+        {
+            // Case 1.
+            remaining = mappedFullName.substr(pos + 1);  // Skip "."
+        }
+        for (size_t ii = 0; ii < this->fields.size(); ++ii)
+        {
+            const ShaderVariable *fieldVar = NULL;
+            std::string originalFieldName;
+            bool found = fields[ii].findInfoByMappedName(
+                remaining, &fieldVar, &originalFieldName);
+            if (found)
+            {
+                *originalFullName = originalName + "." + originalFieldName;
+                *leafVar = fieldVar;
+                return true;
+            }
+        }
+        return false;
+    }
+}
+
+bool ShaderVariable::isSameVariableAtLinkTime(
+    const ShaderVariable &other, bool matchPrecision) const
+{
+    if (type != other.type)
+        return false;
+    if (matchPrecision && precision != other.precision)
+        return false;
+    if (name != other.name)
+        return false;
+    ASSERT(mappedName == other.mappedName);
+    if (arraySize != other.arraySize)
+        return false;
+    if (fields.size() != other.fields.size())
+        return false;
+    for (size_t ii = 0; ii < fields.size(); ++ii)
+    {
+        if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii],
+                                                 matchPrecision))
+        {
+            return false;
+        }
+    }
+    if (structName != other.structName)
+        return false;
+    return true;
+}
+
 Uniform::Uniform()
 {}
 
@@ -69,6 +191,16 @@ Uniform &Uniform::operator=(const Uniform &other)
     return *this;
 }
 
+bool Uniform::operator==(const Uniform &other) const
+{
+    return ShaderVariable::operator==(other);
+}
+
+bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
+{
+    return ShaderVariable::isSameVariableAtLinkTime(other, true);
+}
+
 Attribute::Attribute()
     : location(-1)
 {}
@@ -88,6 +220,12 @@ Attribute &Attribute::operator=(const Attribute &other)
     return *this;
 }
 
+bool Attribute::operator==(const Attribute &other) const
+{
+    return (ShaderVariable::operator==(other) &&
+            location == other.location);
+}
+
 InterfaceBlockField::InterfaceBlockField()
     : isRowMajorLayout(false)
 {}
@@ -107,6 +245,19 @@ InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &o
     return *this;
 }
 
+bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const
+{
+    return (ShaderVariable::operator==(other) &&
+            isRowMajorLayout == other.isRowMajorLayout);
+}
+
+bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime(
+    const InterfaceBlockField &other) const
+{
+    return (ShaderVariable::isSameVariableAtLinkTime(other, true) &&
+            isRowMajorLayout == other.isRowMajorLayout);
+}
+
 Varying::Varying()
     : interpolation(INTERPOLATION_SMOOTH),
       isInvariant(false)
@@ -129,6 +280,20 @@ Varying &Varying::operator=(const Varying &other)
     return *this;
 }
 
+bool Varying::operator==(const Varying &other) const
+{
+    return (ShaderVariable::operator==(other) &&
+            interpolation == other.interpolation &&
+            isInvariant == other.isInvariant);
+}
+
+bool Varying::isSameVaryingAtLinkTime(const Varying &other) const
+{
+    return (ShaderVariable::isSameVariableAtLinkTime(other, false) &&
+            interpolation == other.interpolation &&
+            isInvariant == other.isInvariant);
+}
+
 InterfaceBlock::InterfaceBlock()
     : arraySize(0),
       layout(BLOCKLAYOUT_PACKED),
diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
index 6b0e0c0a033..9cd74218dc5 100644
--- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
+++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
@@ -31,6 +31,7 @@
 //
 
 #include <assert.h>
+#include <set>
 
 #include "common/angleutils.h"
 #include "compiler/translator/InfoSink.h"
@@ -299,19 +300,21 @@ class TSymbolTableLevel
     tLevel level;
 };
 
-enum ESymbolLevel
-{
-    COMMON_BUILTINS = 0,
-    ESSL1_BUILTINS = 1,
-    ESSL3_BUILTINS = 2,
-    LAST_BUILTIN_LEVEL = ESSL3_BUILTINS,
-    GLOBAL_LEVEL = 3
-};
+// Define ESymbolLevel as int rather than an enum since level can go
+// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the
+// compiler optimizes the >= of the last element to ==.
+typedef int ESymbolLevel;
+const int COMMON_BUILTINS = 0;
+const int ESSL1_BUILTINS = 1;
+const int ESSL3_BUILTINS = 2;
+const int LAST_BUILTIN_LEVEL = ESSL3_BUILTINS;
+const int GLOBAL_LEVEL = 3;
 
 class TSymbolTable
 {
   public:
     TSymbolTable()
+        : mGlobalInvariant(false)
     {
         // The symbol table cannot be used until push() is called, but
         // the lack of an initial call to push() can be used to detect
@@ -408,6 +411,25 @@ class TSymbolTable
     // for the specified TBasicType
     TPrecision getDefaultPrecision(TBasicType type) const;
 
+    // This records invariant varyings declared through
+    // "invariant varying_name;".
+    void addInvariantVarying(const TString &originalName)
+    {
+        mInvariantVaryings.insert(originalName);
+    }
+    // If this returns false, the varying could still be invariant
+    // if it is set as invariant during the varying variable
+    // declaration - this piece of information is stored in the
+    // variable's type, not here.
+    bool isVaryingInvariant(const TString &originalName) const
+    {
+      return (mGlobalInvariant ||
+              mInvariantVaryings.count(originalName) > 0);
+    }
+
+    void setGlobalInvariant() { mGlobalInvariant = true; }
+    bool getGlobalInvariant() const { return mGlobalInvariant; }
+
     static int nextUniqueId()
     {
         return ++uniqueIdCounter;
@@ -423,6 +445,9 @@ class TSymbolTable
     typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
     std::vector< PrecisionStackLevel *> precisionStack;
 
+    std::set<TString> mInvariantVaryings;
+    bool mGlobalInvariant;
+
     static int uniqueIdCounter;
 };
 
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp
index 5b99fea9489..dcbf3cea1d4 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp
@@ -16,6 +16,8 @@ TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec)
 void TranslatorESSL::translate(TIntermNode* root) {
     TInfoSinkBase& sink = getInfoSink().obj;
 
+    writePragma();
+
     // Write built-in extension behaviors.
     writeExtensionBehavior();
 
@@ -37,8 +39,13 @@ void TranslatorESSL::writeExtensionBehavior() {
     for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin();
          iter != extensionBehavior.end(); ++iter) {
         if (iter->second != EBhUndefined) {
-            sink << "#extension " << iter->first << " : "
-                 << getBehaviorString(iter->second) << "\n";
+            if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") {
+                sink << "#extension GL_NV_draw_buffers : "
+                     << getBehaviorString(iter->second) << "\n";
+            } else {
+                sink << "#extension " << iter->first << " : "
+                     << getBehaviorString(iter->second) << "\n";
+            }
         }
     }
 }
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
index 4b2aecab33a..6acbf7c5a84 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
@@ -9,18 +9,6 @@
 #include "compiler/translator/OutputGLSL.h"
 #include "compiler/translator/VersionGLSL.h"
 
-static void writeVersion(sh::GLenum type, TIntermNode* root,
-                         TInfoSinkBase& sink) {
-    TVersionGLSL versionGLSL(type);
-    root->traverse(&versionGLSL);
-    int version = versionGLSL.getVersion();
-    // We need to write version directive only if it is greater than 110.
-    // If there is no version directive in the shader, 110 is implied.
-    if (version > 110) {
-        sink << "#version " << version << "\n";
-    }
-}
-
 TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec)
     : TCompiler(type, spec, SH_GLSL_OUTPUT) {
 }
@@ -29,7 +17,9 @@ void TranslatorGLSL::translate(TIntermNode* root) {
     TInfoSinkBase& sink = getInfoSink().obj;
 
     // Write GLSL version.
-    writeVersion(getShaderType(), root, sink);
+    writeVersion(root);
+
+    writePragma();
 
     // Write extension behaviour as needed
     writeExtensionBehavior();
@@ -46,6 +36,20 @@ void TranslatorGLSL::translate(TIntermNode* root) {
     root->traverse(&outputGLSL);
 }
 
+void TranslatorGLSL::writeVersion(TIntermNode *root)
+{
+    TVersionGLSL versionGLSL(getShaderType(), getPragma());
+    root->traverse(&versionGLSL);
+    int version = versionGLSL.getVersion();
+    // We need to write version directive only if it is greater than 110.
+    // If there is no version directive in the shader, 110 is implied.
+    if (version > 110)
+    {
+        TInfoSinkBase& sink = getInfoSink().obj;
+        sink << "#version " << version << "\n";
+    }
+}
+
 void TranslatorGLSL::writeExtensionBehavior() {
     TInfoSinkBase& sink = getInfoSink().obj;
     const TExtensionBehavior& extensionBehavior = getExtensionBehavior();
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h
index 3c6c2e426af..766d8d910e4 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h
@@ -9,14 +9,16 @@
 
 #include "compiler/translator/Compiler.h"
 
-class TranslatorGLSL : public TCompiler {
-public:
+class TranslatorGLSL : public TCompiler
+{
+  public:
     TranslatorGLSL(sh::GLenum type, ShShaderSpec spec);
 
-protected:
-    virtual void translate(TIntermNode* root);
+  protected:
+    virtual void translate(TIntermNode *root);
 
-private:
+  private:
+    void writeVersion(TIntermNode *root);
     void writeExtensionBehavior();
 };
 
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp
index c1a7b7524f1..896e1cd7a01 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp
@@ -94,6 +94,7 @@ const char *GetOperatorString(TOperator op)
       case EOpLogicalXor: return "^^";
       case EOpLogicalAnd: return "&&";
       case EOpNegative: return "-";
+      case EOpPositive: return "+";
       case EOpVectorLogicalNot: return "not";
       case EOpLogicalNot: return "!";
       case EOpPostIncrement: return "++";
diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp
index f26c1566ac8..d8e13788b79 100644
--- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp
@@ -5,6 +5,7 @@
 //
 
 #include "angle_gl.h"
+#include "compiler/translator/SymbolTable.h"
 #include "compiler/translator/VariableInfo.h"
 #include "compiler/translator/util.h"
 #include "common/utilities.h"
@@ -131,7 +132,8 @@ CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
                                    std::vector<sh::Uniform> *uniforms,
                                    std::vector<sh::Varying> *varyings,
                                    std::vector<sh::InterfaceBlock> *interfaceBlocks,
-                                   ShHashFunction64 hashFunction)
+                                   ShHashFunction64 hashFunction,
+                                   const TSymbolTable &symbolTable)
     : mAttribs(attribs),
       mOutputVariables(outputVariables),
       mUniforms(uniforms),
@@ -140,7 +142,10 @@ CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
       mPointCoordAdded(false),
       mFrontFacingAdded(false),
       mFragCoordAdded(false),
-      mHashFunction(hashFunction)
+      mPositionAdded(false),
+      mPointSizeAdded(false),
+      mHashFunction(hashFunction),
+      mSymbolTable(symbolTable)
 {
 }
 
@@ -200,12 +205,14 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
             if (!mFragCoordAdded)
             {
                 Varying info;
-                info.name = "gl_FragCoord";
-                info.mappedName = "gl_FragCoord";
+                const char kName[] = "gl_FragCoord";
+                info.name = kName;
+                info.mappedName = kName;
                 info.type = GL_FLOAT_VEC4;
                 info.arraySize = 0;
-                info.precision = GL_MEDIUM_FLOAT;  // Use mediump as it doesn't really matter.
+                info.precision = GL_MEDIUM_FLOAT;  // Defined by spec.
                 info.staticUse = true;
+                info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
                 mVaryings->push_back(info);
                 mFragCoordAdded = true;
             }
@@ -214,12 +221,14 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
             if (!mFrontFacingAdded)
             {
                 Varying info;
-                info.name = "gl_FrontFacing";
-                info.mappedName = "gl_FrontFacing";
+                const char kName[] = "gl_FrontFacing";
+                info.name = kName;
+                info.mappedName = kName;
                 info.type = GL_BOOL;
                 info.arraySize = 0;
                 info.precision = GL_NONE;
                 info.staticUse = true;
+                info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
                 mVaryings->push_back(info);
                 mFrontFacingAdded = true;
             }
@@ -228,16 +237,50 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
             if (!mPointCoordAdded)
             {
                 Varying info;
-                info.name = "gl_PointCoord";
-                info.mappedName = "gl_PointCoord";
+                const char kName[] = "gl_PointCoord";
+                info.name = kName;
+                info.mappedName = kName;
                 info.type = GL_FLOAT_VEC2;
                 info.arraySize = 0;
-                info.precision = GL_MEDIUM_FLOAT;  // Use mediump as it doesn't really matter.
+                info.precision = GL_MEDIUM_FLOAT;  // Defined by spec.
                 info.staticUse = true;
+                info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
                 mVaryings->push_back(info);
                 mPointCoordAdded = true;
             }
             return;
+          case EvqPosition:
+            if (!mPositionAdded)
+            {
+                Varying info;
+                const char kName[] = "gl_Position";
+                info.name = kName;
+                info.mappedName = kName;
+                info.type = GL_FLOAT_VEC4;
+                info.arraySize = 0;
+                info.precision = GL_HIGH_FLOAT;  // Defined by spec.
+                info.staticUse = true;
+                info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
+                mVaryings->push_back(info);
+                mPositionAdded = true;
+            }
+            return;
+          case EvqPointSize:
+            if (!mPointSizeAdded)
+            {
+                Varying info;
+                const char kName[] = "gl_PointSize";
+                info.name = kName;
+                info.mappedName = kName;
+                info.type = GL_FLOAT;
+                info.arraySize = 0;
+                info.precision = GL_MEDIUM_FLOAT;  // Defined by spec.
+                info.staticUse = true;
+                info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
+                mVaryings->push_back(info);
+                mPointSizeAdded = true;
+            }
+            return;
           default:
             break;
         }
@@ -251,8 +294,10 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
 class NameHashingTraverser : public GetVariableTraverser
 {
   public:
-    NameHashingTraverser(ShHashFunction64 hashFunction)
-        : mHashFunction(hashFunction)
+    NameHashingTraverser(ShHashFunction64 hashFunction,
+                         const TSymbolTable &symbolTable)
+        : GetVariableTraverser(symbolTable),
+          mHashFunction(hashFunction)
     {}
 
   private:
@@ -312,7 +357,7 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable,
         const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field);
         const TType &fieldType = *field.type();
 
-        GetVariableTraverser traverser;
+        GetVariableTraverser traverser(mSymbolTable);
         traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields);
 
         interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
@@ -325,7 +370,7 @@ template <typename VarT>
 void CollectVariables::visitVariable(const TIntermSymbol *variable,
                                      std::vector<VarT> *infoList) const
 {
-    NameHashingTraverser traverser(mHashFunction);
+    NameHashingTraverser traverser(mHashFunction, mSymbolTable);
     traverser.traverse(variable->getType(), variable->getSymbol(), infoList);
 }
 
@@ -421,9 +466,8 @@ bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
     return true;
 }
 
-template <typename VarT>
-void ExpandVariables(const std::vector<VarT> &compact,
-                     std::vector<ShaderVariable> *expanded)
+void ExpandUniforms(const std::vector<Uniform> &compact,
+                    std::vector<ShaderVariable> *expanded)
 {
     for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
     {
@@ -432,7 +476,4 @@ void ExpandVariables(const std::vector<VarT> &compact,
     }
 }
 
-template void ExpandVariables(const std::vector<Uniform> &, std::vector<ShaderVariable> *);
-template void ExpandVariables(const std::vector<Varying> &, std::vector<ShaderVariable> *);
-
 }
diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h
index 5ac4c46baa5..92d376d8795 100644
--- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h
+++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h
@@ -11,6 +11,8 @@
 
 #include "compiler/translator/IntermNode.h"
 
+class TSymbolTable;
+
 namespace sh
 {
 
@@ -23,7 +25,8 @@ class CollectVariables : public TIntermTraverser
                      std::vector<Uniform> *uniforms,
                      std::vector<Varying> *varyings,
                      std::vector<InterfaceBlock> *interfaceBlocks,
-                     ShHashFunction64 hashFunction);
+                     ShHashFunction64 hashFunction,
+                     const TSymbolTable &symbolTable);
 
     virtual void visitSymbol(TIntermSymbol *symbol);
     virtual bool visitAggregate(Visit, TIntermAggregate *node);
@@ -48,13 +51,17 @@ class CollectVariables : public TIntermTraverser
     bool mFrontFacingAdded;
     bool mFragCoordAdded;
 
+    bool mPositionAdded;
+    bool mPointSizeAdded;
+
     ShHashFunction64 mHashFunction;
+
+    const TSymbolTable &mSymbolTable;
 };
 
-// Expand struct variables to flattened lists of split variables
-template <typename VarT>
-void ExpandVariables(const std::vector<VarT> &compact,
-                     std::vector<ShaderVariable> *expanded);
+// Expand struct uniforms to flattened lists of split variables
+void ExpandUniforms(const std::vector<Uniform> &compact,
+                    std::vector<ShaderVariable> *expanded);
 
 }
 
diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp
index 8edbd009b06..05b111a7a74 100644
--- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp
@@ -26,18 +26,12 @@ static const int GLSL_VERSION_120 = 120;
 //    GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that
 //    are built-in types, entire structures or arrays... are all l-values."
 //
-// TODO(alokp): The following two cases of invariant decalaration get lost
-// during parsing - they do not get carried over to the intermediate tree.
-// Handle these cases:
-// 1. When a pragma is used to force all output variables to be invariant:
-//    - #pragma STDGL invariant(all)
-// 2. When a previously decalared or built-in variable is marked invariant:
-//    - invariant gl_Position;
-//    - varying vec3 color; invariant color;
-//
-TVersionGLSL::TVersionGLSL(sh::GLenum type)
-    : mVersion(GLSL_VERSION_110)
+TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma)
 {
+    if (pragma.stdgl.invariantAll)
+        mVersion = GLSL_VERSION_120;
+    else
+        mVersion = GLSL_VERSION_110;
 }
 
 void TVersionGLSL::visitSymbol(TIntermSymbol *node)
diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h
index 30f5a138a0f..72368e39d66 100644
--- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h
@@ -9,6 +9,8 @@
 
 #include "compiler/translator/IntermNode.h"
 
+#include "compiler/translator/Pragma.h"
+
 // Traverses the intermediate tree to return the minimum GLSL version
 // required to legally access all built-in features used in the shader.
 // GLSL 1.1 which is mandated by OpenGL 2.0 provides:
@@ -27,7 +29,7 @@
 class TVersionGLSL : public TIntermTraverser
 {
   public:
-    TVersionGLSL(sh::GLenum type);
+    TVersionGLSL(sh::GLenum type, const TPragma &pragma);
 
     // Returns 120 if the following is used the shader:
     // - "invariant",
diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y
index 5c945ad5adc..e271de978c0 100644
--- a/src/3rdparty/angle/src/compiler/translator/glslang.y
+++ b/src/3rdparty/angle/src/compiler/translator/glslang.y
@@ -354,6 +354,15 @@ function_call
                         // Treat it like a built-in unary operator.
                         //
                         $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1);
+                        const TType& returnType = fnCandidate->getReturnType();
+                        if (returnType.getBasicType() == EbtBool) {
+                            // Bool types should not have precision, so we'll override any precision
+                            // that might have been set by addUnaryMath.
+                            $$->setType(returnType);
+                        } else {
+                            // addUnaryMath has set the precision of the node based on the operand.
+                            $$->setTypePreservePrecision(returnType);
+                        }
                         if ($$ == 0)  {
                             std::stringstream extraInfoStream;
                             extraInfoStream << "built in unary operator function.  Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
@@ -362,20 +371,29 @@ function_call
                             YYERROR;
                         }
                     } else {
-                        $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
+                        TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
+                        aggregate->setType(fnCandidate->getReturnType());
+                        aggregate->setPrecisionFromChildren();
+                        $$ = aggregate;
                     }
                 } else {
                     // This is a real function call
 
-                    $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
-                    $$->setType(fnCandidate->getReturnType());
+                    TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
+                    aggregate->setType(fnCandidate->getReturnType());
 
                     // this is how we know whether the given function is a builtIn function or a user defined function
                     // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
                     // if builtIn == true, it's definitely a builtIn function with EOpNull
                     if (!builtIn)
-                        $$->getAsAggregate()->setUserDefined();
-                    $$->getAsAggregate()->setName(fnCandidate->getMangledName());
+                        aggregate->setUserDefined();
+                    aggregate->setName(fnCandidate->getMangledName());
+
+                    // This needs to happen after the name is set
+                    if (builtIn)
+                        aggregate->setBuiltInFunctionPrecision();
+
+                    $$ = aggregate;
 
                     TQualifier qual;
                     for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
@@ -388,7 +406,6 @@ function_call
                         }
                     }
                 }
-                $$->setType(fnCandidate->getReturnType());
             } else {
                 // error message was put out by PaFindFunction()
                 // Put on a dummy node for error recovery
@@ -500,6 +517,7 @@ unary_expression
                 const char* errorOp = "";
                 switch($1.op) {
                 case EOpNegative:   errorOp = "-"; break;
+                case EOpPositive:   errorOp = "+"; break;
                 case EOpLogicalNot: errorOp = "!"; break;
                 default: break;
                 }
@@ -514,7 +532,7 @@ unary_expression
 // Grammar Note:  No traditional style type casts.
 
 unary_operator
-    : PLUS  { $$.op = EOpNull; }
+    : PLUS  { $$.op = EOpPositive; }
     | DASH  { $$.op = EOpNegative; }
     | BANG  { $$.op = EOpLogicalNot; }
     ;
@@ -762,7 +780,7 @@ declaration
         
         TIntermAggregate *prototype = new TIntermAggregate;
         prototype->setType(function.getReturnType());
-        prototype->setName(function.getName());
+        prototype->setName(function.getMangledName());
         
         for (size_t i = 0; i < function.getParamCount(); i++)
         {
diff --git a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp
index 56340c6f9e7..00780f04543 100644
--- a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp
@@ -62,7 +62,9 @@ TString TType::getCompleteString() const
     TStringStream stream;
 
     if (qualifier != EvqTemporary && qualifier != EvqGlobal)
-        stream << getQualifierString() << " " << getPrecisionString() << " ";
+        stream << getQualifierString() << " ";
+    if (precision != EbpUndefined)
+        stream << getPrecisionString() << " ";
     if (array)
         stream << "array[" << getArraySize() << "] of ";
     if (isMatrix())
@@ -221,6 +223,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
     switch (node->getOp())
     {
       case EOpNegative:       out << "Negate value";         break;
+      case EOpPositive:       out << "Positive sign";        break;
       case EOpVectorLogicalNot:
       case EOpLogicalNot:     out << "Negate conditional";   break;
 
@@ -292,6 +295,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
       case EOpFunction:      out << "Function Definition: " << node->getName(); break;
       case EOpFunctionCall:  out << "Function Call: " << node->getName(); break;
       case EOpParameters:    out << "Function Parameters: ";              break;
+      case EOpPrototype:     out << "Function Prototype: " << node->getName(); break;
 
       case EOpConstructFloat: out << "Construct float"; break;
       case EOpConstructVec2:  out << "Construct vec2";  break;
diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp
index f74c7d11731..8cc06a658a5 100644
--- a/src/3rdparty/angle/src/compiler/translator/util.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/util.cpp
@@ -9,6 +9,7 @@
 #include <limits>
 
 #include "compiler/preprocessor/numeric_lex.h"
+#include "compiler/translator/SymbolTable.h"
 #include "common/utilities.h"
 
 bool atof_clamp(const char *str, float *value)
@@ -281,8 +282,47 @@ InterpolationType GetInterpolationType(TQualifier qualifier)
     }
 }
 
+GetVariableTraverser::GetVariableTraverser(const TSymbolTable &symbolTable)
+    : mSymbolTable(symbolTable)
+{
+}
+
+template void GetVariableTraverser::setTypeSpecificInfo(
+    const TType &type, const TString& name, InterfaceBlockField *variable);
+template void GetVariableTraverser::setTypeSpecificInfo(
+    const TType &type, const TString& name, ShaderVariable *variable);
+template void GetVariableTraverser::setTypeSpecificInfo(
+    const TType &type, const TString& name, Uniform *variable);
+
+template<>
+void GetVariableTraverser::setTypeSpecificInfo(
+    const TType &type, const TString& name, Varying *variable)
+{
+    ASSERT(variable);
+    switch (type.getQualifier())
+    {
+      case EvqInvariantVaryingIn:
+      case EvqInvariantVaryingOut:
+        variable->isInvariant = true;
+        break;
+      case EvqVaryingIn:
+      case EvqVaryingOut:
+        if (mSymbolTable.isVaryingInvariant(name))
+        {
+            variable->isInvariant = true;
+        }
+        break;
+      default:
+        break;
+    }
+
+    variable->interpolation = GetInterpolationType(type.getQualifier());
+}
+
 template <typename VarT>
-void GetVariableTraverser::traverse(const TType &type, const TString &name, std::vector<VarT> *output)
+void GetVariableTraverser::traverse(const TType &type,
+                                    const TString &name,
+                                    std::vector<VarT> *output)
 {
     const TStructure *structure = type.getStruct();
 
@@ -309,15 +349,16 @@ void GetVariableTraverser::traverse(const TType &type, const TString &name, std:
             traverse(*field->type(), field->name(), &variable.fields);
         }
     }
-
+    setTypeSpecificInfo(type, name, &variable);
     visitVariable(&variable);
 
     ASSERT(output);
     output->push_back(variable);
 }
 
+template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *);
+template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<ShaderVariable> *);
 template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *);
 template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *);
-template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *);
 
 }
diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h
index 241e2cc1c20..fb5308759e3 100644
--- a/src/3rdparty/angle/src/compiler/translator/util.h
+++ b/src/3rdparty/angle/src/compiler/translator/util.h
@@ -24,6 +24,8 @@ extern bool atof_clamp(const char *str, float *value);
 // Return false if overflow happens.
 extern bool atoi_clamp(const char *str, int *value);
 
+class TSymbolTable;
+
 namespace sh
 {
 
@@ -38,7 +40,7 @@ TString ArrayString(const TType &type);
 class GetVariableTraverser
 {
   public:
-    GetVariableTraverser() {}
+    GetVariableTraverser(const TSymbolTable &symbolTable);
 
     template <typename VarT>
     void traverse(const TType &type, const TString &name, std::vector<VarT> *output);
@@ -48,6 +50,14 @@ class GetVariableTraverser
     virtual void visitVariable(ShaderVariable *newVar) {}
 
   private:
+    // Helper function called by traverse() to fill specific fields
+    // for attributes/varyings/uniforms.
+    template <typename VarT>
+    void setTypeSpecificInfo(
+        const TType &type, const TString &name, VarT *variable) {}
+
+    const TSymbolTable &mSymbolTable;
+
     DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser);
 };
 
diff --git a/src/3rdparty/angle/src/libEGL/AttributeMap.cpp b/src/3rdparty/angle/src/libEGL/AttributeMap.cpp
new file mode 100644
index 00000000000..28dd3d842ec
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/AttributeMap.cpp
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "libEGL/AttributeMap.h"
+
+namespace egl
+{
+
+AttributeMap::AttributeMap()
+{
+}
+
+AttributeMap::AttributeMap(const EGLint *attributes)
+{
+    for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
+    {
+        insert(curAttrib[0], curAttrib[1]);
+    }
+}
+
+void AttributeMap::insert(EGLint key, EGLint value)
+{
+    mAttributes[key] = value;
+}
+
+bool AttributeMap::contains(EGLint key) const
+{
+    return (mAttributes.find(key) != mAttributes.end());
+}
+
+EGLint AttributeMap::get(EGLint key, EGLint defaultValue) const
+{
+    std::map<EGLint, EGLint>::const_iterator iter = mAttributes.find(key);
+    return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libEGL/AttributeMap.h b/src/3rdparty/angle/src/libEGL/AttributeMap.h
new file mode 100644
index 00000000000..f2f082fe219
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/AttributeMap.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef LIBEGL_ATTRIBUTEMAP_H_
+#define LIBEGL_ATTRIBUTEMAP_H_
+
+#include <EGL/egl.h>
+
+#include <map>
+
+namespace egl
+{
+
+class AttributeMap
+{
+  public:
+    AttributeMap();
+    explicit AttributeMap(const EGLint *attributes);
+
+    virtual void insert(EGLint key, EGLint value);
+    virtual bool contains(EGLint key) const;
+    virtual EGLint get(EGLint key, EGLint defaultValue) const;
+
+  private:
+    std::map<EGLint, EGLint> mAttributes;
+};
+
+}
+
+#endif   // LIBEGL_ATTRIBUTEMAP_H_
diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp
index 5a50e4baf54..eea93b1d872 100644
--- a/src/3rdparty/angle/src/libEGL/Display.cpp
+++ b/src/3rdparty/angle/src/libEGL/Display.cpp
@@ -35,32 +35,36 @@ static DisplayMap *GetDisplayMap()
     return &displays;
 }
 
-egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, EGLint displayType)
+egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap)
 {
+    Display *display = NULL;
+
     DisplayMap *displays = GetDisplayMap();
     DisplayMap::const_iterator iter = displays->find(displayId);
     if (iter != displays->end())
     {
-        return iter->second;
+        display = iter->second;
+    }
+    else
+    {
+        display = new egl::Display(displayId);
+        displays->insert(std::make_pair(displayId, display));
     }
-    
-    // FIXME: Check if displayId is a valid display device context
 
-    egl::Display *display = new egl::Display(displayId, displayType);
-    displays->insert(std::make_pair(displayId, display));
+    // Apply new attributes if the display is not initialized yet.
+    if (!display->isInitialized())
+    {
+        display->setAttributes(attribMap);
+    }
 
     return display;
 }
 
-Display::Display(EGLNativeDisplayType displayId, EGLint displayType)
+Display::Display(EGLNativeDisplayType displayId)
     : mDisplayId(displayId),
-      mRequestedDisplayType(displayType),
+      mAttributeMap(),
       mRenderer(NULL)
 {
-#if defined(ANGLE_PLATFORM_WINRT)
-    if (mDisplayId)
-        mDisplayId->AddRef();
-#endif
 }
 
 Display::~Display()
@@ -73,28 +77,29 @@ Display::~Display()
     {
         displays->erase(iter);
     }
+}
 
-#if defined(ANGLE_PLATFORM_WINRT)
-    if (mDisplayId)
-        mDisplayId->Release();
-#endif
+void Display::setAttributes(const AttributeMap &attribMap)
+{
+    mAttributeMap = attribMap;
 }
 
-bool Display::initialize()
+Error Display::initialize()
 {
     if (isInitialized())
     {
-        return true;
+        return Error(EGL_SUCCESS);
     }
 
-    mRenderer = glCreateRenderer(this, mDisplayId, mRequestedDisplayType);
+    mRenderer = glCreateRenderer(this, mDisplayId, mAttributeMap);
 
     if (!mRenderer)
     {
         terminate();
-        return error(EGL_NOT_INITIALIZED, false);
+        return Error(EGL_NOT_INITIALIZED);
     }
 
+    //TODO(jmadill): should be part of caps?
     EGLint minSwapInterval = mRenderer->getMinSwapInterval();
     EGLint maxSwapInterval = mRenderer->getMaxSwapInterval();
     EGLint maxTextureSize = mRenderer->getRendererCaps().max2DTextureSize;
@@ -125,13 +130,13 @@ bool Display::initialize()
     if (!isInitialized())
     {
         terminate();
-        return false;
+        return Error(EGL_NOT_INITIALIZED);
     }
 
     initDisplayExtensionString();
     initVendorString();
 
-    return true;
+    return Error(EGL_SUCCESS);
 }
 
 void Display::terminate()
@@ -148,6 +153,8 @@ void Display::terminate()
 
     glDestroyRenderer(mRenderer);
     mRenderer = NULL;
+
+    mConfigSet.mSet.clear();
 }
 
 bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
@@ -202,7 +209,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
 
 
 
-EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList)
+Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface)
 {
     const Config *configuration = mConfigSet.get(config);
     EGLint postSubBufferSupported = EGL_FALSE;
@@ -223,9 +230,9 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co
                   case EGL_BACK_BUFFER:
                     break;
                   case EGL_SINGLE_BUFFER:
-                    return error(EGL_BAD_MATCH, EGL_NO_SURFACE);   // Rendering directly to front buffer not supported
+                    return Error(EGL_BAD_MATCH);   // Rendering directly to front buffer not supported
                   default:
-                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                    return Error(EGL_BAD_ATTRIBUTE);
                 }
                 break;
               case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
@@ -241,11 +248,11 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co
                 fixedSize = attribList[1];
                 break;
               case EGL_VG_COLORSPACE:
-                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+                return Error(EGL_BAD_MATCH);
               case EGL_VG_ALPHA_FORMAT:
-                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+                return Error(EGL_BAD_MATCH);
               default:
-                return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                return Error(EGL_BAD_ATTRIBUTE);
             }
 
             attribList += 2;
@@ -254,7 +261,7 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co
 
     if (width < 0 || height < 0)
     {
-        return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+        return Error(EGL_BAD_PARAMETER);
     }
 
     if (!fixedSize)
@@ -265,29 +272,33 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co
 
     if (hasExistingWindowSurface(window))
     {
-        return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
+        return Error(EGL_BAD_ALLOC);
     }
 
     if (mRenderer->testDeviceLost(false))
     {
-        if (!restoreLostDevice())
-            return EGL_NO_SURFACE;
+        Error error = restoreLostDevice();
+        if (error.isError())
+        {
+            return error;
+        }
     }
 
     Surface *surface = new Surface(this, configuration, window, fixedSize, width, height, postSubBufferSupported);
-
-    if (!surface->initialize())
+    Error error = surface->initialize();
+    if (error.isError())
     {
-        delete surface;
-        return EGL_NO_SURFACE;
+        SafeDelete(surface);
+        return error;
     }
 
     mSurfaceSet.insert(surface);
 
-    return success(surface);
+    *outSurface = surface;
+    return Error(EGL_SUCCESS);
 }
 
-EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList)
+Error Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface)
 {
     EGLint width = 0, height = 0;
     EGLenum textureFormat = EGL_NO_TEXTURE;
@@ -319,7 +330,7 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle,
                     textureFormat = attribList[1];
                     break;
                   default:
-                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                    return Error(EGL_BAD_ATTRIBUTE);
                 }
                 break;
               case EGL_TEXTURE_TARGET:
@@ -330,19 +341,19 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle,
                     textureTarget = attribList[1];
                     break;
                   default:
-                    return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                    return Error(EGL_BAD_ATTRIBUTE);
                 }
                 break;
               case EGL_MIPMAP_TEXTURE:
                 if (attribList[1] != EGL_FALSE)
-                  return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                  return Error(EGL_BAD_ATTRIBUTE);
                 break;
               case EGL_VG_COLORSPACE:
-                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+                return Error(EGL_BAD_MATCH);
               case EGL_VG_ALPHA_FORMAT:
-                return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+                return Error(EGL_BAD_MATCH);
               default:
-                return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                return Error(EGL_BAD_ATTRIBUTE);
             }
 
             attribList += 2;
@@ -351,88 +362,100 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle,
 
     if (width < 0 || height < 0)
     {
-        return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+        return Error(EGL_BAD_PARAMETER);
     }
 
     if (width == 0 || height == 0)
     {
-        return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+        return Error(EGL_BAD_ATTRIBUTE);
     }
 
     if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getRendererExtensions().textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
     {
-        return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+        return Error(EGL_BAD_MATCH);
     }
 
     if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
         (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
     {
-        return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+        return Error(EGL_BAD_MATCH);
     }
 
     if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT))
     {
-        return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
+        return Error(EGL_BAD_MATCH);
     }
 
     if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
         (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE))
     {
-        return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+        return Error(EGL_BAD_ATTRIBUTE);
     }
 
     if (mRenderer->testDeviceLost(false))
     {
-        if (!restoreLostDevice())
-            return EGL_NO_SURFACE;
+        Error error = restoreLostDevice();
+        if (error.isError())
+        {
+            return error;
+        }
     }
 
     Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget);
-
-    if (!surface->initialize())
+    Error error = surface->initialize();
+    if (error.isError())
     {
-        delete surface;
-        return EGL_NO_SURFACE;
+        SafeDelete(surface);
+        return error;
     }
 
     mSurfaceSet.insert(surface);
 
-    return success(surface);
+    *outSurface = surface;
+    return Error(EGL_SUCCESS);
 }
 
-EGLContext Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
+Error Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets,
+                             bool robustAccess, EGLContext *outContext)
 {
     if (!mRenderer)
     {
-        return EGL_NO_CONTEXT;
+        *outContext = EGL_NO_CONTEXT;
+        return Error(EGL_SUCCESS);
     }
     else if (mRenderer->testDeviceLost(false))   // Lost device
     {
-        if (!restoreLostDevice())
+        Error error = restoreLostDevice();
+        if (error.isError())
         {
-            return error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT);
+            return error;
         }
     }
 
+    //TODO(jmadill): shader model is not cross-platform
     if (clientVersion > 2 && mRenderer->getMajorShaderModel() < 4)
     {
-        return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
+        return Error(EGL_BAD_CONFIG);
     }
 
     gl::Context *context = glCreateContext(clientVersion, shareContext, mRenderer, notifyResets, robustAccess);
     mContextSet.insert(context);
 
-    return success(context);
+    *outContext = context;
+    return Error(EGL_SUCCESS);
 }
 
-bool Display::restoreLostDevice()
+Error Display::restoreLostDevice()
 {
     for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
     {
         if ((*ctx)->isResetNotificationEnabled())
-            return false;   // If reset notifications have been requested, application must delete all contexts first
+        {
+            // If reset notifications have been requested, application must delete all contexts first
+            return Error(EGL_CONTEXT_LOST);
+        }
     }
- 
+
     // Release surface resources to make the Reset() succeed
     for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
     {
@@ -441,16 +464,20 @@ bool Display::restoreLostDevice()
 
     if (!mRenderer->resetDevice())
     {
-        return error(EGL_BAD_ALLOC, false);
+        return Error(EGL_BAD_ALLOC);
     }
 
     // Restore any surfaces that may have been lost
     for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
     {
-        (*surface)->resetSwapChain();
+        Error error = (*surface)->resetSwapChain();
+        if (error.isError())
+        {
+            return error;
+        }
     }
 
-    return true;
+    return Error(EGL_SUCCESS);
 }
 
 
@@ -472,7 +499,6 @@ void Display::notifyDeviceLost()
     {
         (*context)->markContextLost();
     }
-    egl::error(EGL_CONTEXT_LOST);
 }
 
 void Display::recreateSwapChains()
@@ -604,10 +630,11 @@ void Display::initVendorString()
 
     LUID adapterLuid = {0};
 
+    //TODO(jmadill): LUID is not cross-platform
     if (mRenderer && mRenderer->getLUID(&adapterLuid))
     {
         char adapterLuidString[64];
-        snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
+        sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
 
         mVendorString += adapterLuidString;
     }
diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h
index 73ba7673ffb..b3ffcc84c5c 100644
--- a/src/3rdparty/angle/src/libEGL/Display.h
+++ b/src/3rdparty/angle/src/libEGL/Display.h
@@ -14,7 +14,9 @@
 #include <set>
 #include <vector>
 
+#include "libEGL/Error.h"
 #include "libEGL/Config.h"
+#include "libEGL/AttributeMap.h"
 
 namespace gl
 {
@@ -30,10 +32,10 @@ class Display
   public:
     ~Display();
 
-    bool initialize();
+    Error initialize();
     void terminate();
 
-    static egl::Display *getDisplay(EGLNativeDisplayType displayId, EGLint displayType);
+    static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap);
 
     static const char *getExtensionString(egl::Display *display);
 
@@ -43,9 +45,10 @@ class Display
     bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
     bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
 
-    EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList);
-    EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList);
-    EGLContext createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
+    Error createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface);
+    Error createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface);
+    Error createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets,
+                        bool robustAccess, EGLContext *outContext);
 
     void destroySurface(egl::Surface *surface);
     void destroyContext(gl::Context *context);
@@ -64,18 +67,19 @@ class Display
 
     const char *getExtensionString() const;
     const char *getVendorString() const;
-
     EGLNativeDisplayType getDisplayId() const { return mDisplayId; }
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Display);
 
-    Display(EGLNativeDisplayType displayId, EGLint displayType);
+    Display(EGLNativeDisplayType displayId);
+
+    void setAttributes(const AttributeMap &attribMap);
 
-    bool restoreLostDevice();
+    Error restoreLostDevice();
 
     EGLNativeDisplayType mDisplayId;
-    EGLint mRequestedDisplayType;
+    AttributeMap mAttributeMap;
 
     typedef std::set<Surface*> SurfaceSet;
     SurfaceSet mSurfaceSet;
diff --git a/src/3rdparty/angle/src/libEGL/Error.cpp b/src/3rdparty/angle/src/libEGL/Error.cpp
new file mode 100644
index 00000000000..df5f163d328
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/Error.cpp
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Error.cpp: Implements the egl::Error class which encapsulates an EGL error
+// and optional error message.
+
+#include "libEGL/Error.h"
+
+#include "common/angleutils.h"
+
+#include <cstdarg>
+
+namespace egl
+{
+
+Error::Error(EGLint errorCode)
+    : mCode(errorCode),
+      mMessage()
+{
+}
+
+Error::Error(EGLint errorCode, const char *msg, ...)
+    : mCode(errorCode),
+    mMessage()
+{
+    va_list vararg;
+    va_start(vararg, msg);
+    mMessage = FormatString(msg, vararg);
+    va_end(vararg);
+}
+
+Error::Error(const Error &other)
+    : mCode(other.mCode),
+    mMessage(other.mMessage)
+{
+}
+
+Error &Error::operator=(const Error &other)
+{
+    mCode = other.mCode;
+    mMessage = other.mMessage;
+    return *this;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libEGL/Error.h b/src/3rdparty/angle/src/libEGL/Error.h
new file mode 100644
index 00000000000..71805d2fb76
--- /dev/null
+++ b/src/3rdparty/angle/src/libEGL/Error.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Error.h: Defines the egl::Error class which encapsulates an EGL error
+// and optional error message.
+
+#ifndef LIBEGL_ERROR_H_
+#define LIBEGL_ERROR_H_
+
+#include <EGL/egl.h>
+
+#include <string>
+
+namespace egl
+{
+
+class Error
+{
+  public:
+    explicit Error(EGLint errorCode);
+    Error(EGLint errorCode, const char *msg, ...);
+    Error(const Error &other);
+    Error &operator=(const Error &other);
+
+    EGLint getCode() const { return mCode; }
+    bool isError() const { return (mCode != EGL_SUCCESS); }
+
+    const std::string &getMessage() const { return mMessage; }
+
+  private:
+    EGLint mCode;
+    std::string mMessage;
+};
+
+}
+
+#endif // LIBEGL_ERROR_H_
diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp
index fa7996152ad..b664a8530e2 100644
--- a/src/3rdparty/angle/src/libEGL/Surface.cpp
+++ b/src/3rdparty/angle/src/libEGL/Surface.cpp
@@ -22,23 +22,19 @@
 #include "libEGL/main.h"
 #include "libEGL/Display.h"
 
-#if defined(ANGLE_PLATFORM_WINRT)
-#  include "wrl.h"
-#  include "windows.graphics.display.h"
-#  include "windows.ui.core.h"
-using namespace ABI::Windows::Graphics::Display;
-using namespace ABI::Windows::Foundation;
-using namespace ABI::Windows::UI::Core;
-using namespace Microsoft::WRL;
-#endif
+#include "common/NativeWindow.h"
+
+//TODO(jmadill): phase this out
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
 
 namespace egl
 {
 
-Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported)
-    : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
+Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) 
+    : mDisplay(display), mConfig(config), mNativeWindow(window, display->getDisplayId()), mPostSubBufferSupported(postSubBufferSupported)
 {
-    mRenderer = mDisplay->getRenderer();
+    //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
+    mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
     mSwapChain = NULL;
     mShareHandle = NULL;
     mTexture = NULL;
@@ -51,27 +47,19 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win
     mSwapInterval = -1;
     mWidth = width;
     mHeight = height;
+    mFixedWidth = mWidth;
+    mFixedHeight = mHeight;
     setSwapInterval(1);
     mFixedSize = fixedSize;
-    mSwapFlags = rx::SWAP_NORMAL;
-#if defined(ANGLE_PLATFORM_WINRT)
-    if (mWindow)
-        mWindow->AddRef();
-    mScaleFactor = 1.0;
-    mSizeToken.value = 0;
-    mDpiToken.value = 0;
-#   if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-    mOrientationToken.value = 0;
-#   endif
-#endif
 
     subclassWindow();
 }
 
 Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
-    : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
+    : mDisplay(display), mNativeWindow(NULL, NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
 {
-    mRenderer = mDisplay->getRenderer();
+    //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
+    mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
     mSwapChain = NULL;
     mWindowSubclassed = false;
     mTexture = NULL;
@@ -85,90 +73,33 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL
     setSwapInterval(1);
     // This constructor is for offscreen surfaces, which are always fixed-size.
     mFixedSize = EGL_TRUE;
-    mSwapFlags = rx::SWAP_NORMAL;
-#if defined(ANGLE_PLATFORM_WINRT)
-    mScaleFactor = 1.0;
-    mSizeToken.value = 0;
-    mDpiToken.value = 0;
-#   if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-    mOrientationToken.value = 0;
-#   endif
-#endif
+    mFixedWidth = mWidth;
+    mFixedHeight = mHeight;
 }
 
 Surface::~Surface()
 {
-#if defined(ANGLE_PLATFORM_WINRT)
-    if (mSizeToken.value) {
-        ComPtr<ICoreWindow> coreWindow;
-        HRESULT hr = mWindow->QueryInterface(coreWindow.GetAddressOf());
-        ASSERT(SUCCEEDED(hr));
-
-        hr = coreWindow->remove_SizeChanged(mSizeToken);
-        ASSERT(SUCCEEDED(hr));
-    }
-    if (mDpiToken.value) {
-        ComPtr<IDisplayInformation> displayInformation;
-        HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf());
-        ASSERT(SUCCEEDED(hr));
-
-        hr = displayInformation->remove_DpiChanged(mDpiToken);
-        ASSERT(SUCCEEDED(hr));
-    }
-#   if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
-    if (mOrientationToken.value) {
-        ComPtr<IDisplayInformation> displayInformation;
-        HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf());
-        ASSERT(SUCCEEDED(hr));
-
-        hr = displayInformation->remove_OrientationChanged(mOrientationToken);
-        ASSERT(SUCCEEDED(hr));
-    }
-#   endif
-#endif
     unsubclassWindow();
     release();
 }
 
-bool Surface::initialize()
-{
-#if defined(ANGLE_PLATFORM_WINRT)
-    if (!mFixedSize) {
-        HRESULT hr;
-        ComPtr<IDisplayInformation> displayInformation;
-        hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf());
-        ASSERT(SUCCEEDED(hr));
-        onDpiChanged(displayInformation.Get(), 0);
-        hr = displayInformation->add_DpiChanged(Callback<ITypedEventHandler<DisplayInformation *, IInspectable *>>(this, &Surface::onDpiChanged).Get(),
-                                                &mDpiToken);
-        ASSERT(SUCCEEDED(hr));
-
-#   if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-        onOrientationChanged(displayInformation.Get(), 0);
-        hr = displayInformation->add_OrientationChanged(Callback<ITypedEventHandler<DisplayInformation *, IInspectable *>>(this, &Surface::onOrientationChanged).Get(),
-                                                        &mOrientationToken);
-        ASSERT(SUCCEEDED(hr));
-#   endif
-
-        ComPtr<ICoreWindow> coreWindow;
-        hr = mWindow->QueryInterface(coreWindow.GetAddressOf());
-        ASSERT(SUCCEEDED(hr));
-
-        Rect rect;
-        hr = coreWindow->get_Bounds(&rect);
-        ASSERT(SUCCEEDED(hr));
-        mWidth = rect.Width * mScaleFactor;
-        mHeight = rect.Height * mScaleFactor;
-        hr = coreWindow->add_SizeChanged(Callback<ITypedEventHandler<CoreWindow *, WindowSizeChangedEventArgs *>>(this, &Surface::onSizeChanged).Get(),
-                                         &mSizeToken);
-        ASSERT(SUCCEEDED(hr));
+Error Surface::initialize()
+{
+    if (mNativeWindow.getNativeWindow())
+    {
+        if (!mNativeWindow.initialize())
+        {
+            return Error(EGL_BAD_SURFACE);
+        }
     }
-#endif
 
-    if (!resetSwapChain())
-      return false;
+    Error error = resetSwapChain();
+    if (error.isError())
+    {
+        return error;
+    }
 
-    return true;
+    return Error(EGL_SUCCESS);
 }
 
 void Surface::release()
@@ -181,85 +112,80 @@ void Surface::release()
         mTexture->releaseTexImage();
         mTexture = NULL;
     }
-
-#if defined(ANGLE_PLATFORM_WINRT)
-    if (mWindow)
-        mWindow->Release();
-#endif
 }
 
-bool Surface::resetSwapChain()
+Error Surface::resetSwapChain()
 {
     ASSERT(!mSwapChain);
 
     int width;
     int height;
 
-#if !defined(ANGLE_PLATFORM_WINRT)
     if (!mFixedSize)
     {
         RECT windowRect;
-        if (!GetClientRect(getWindowHandle(), &windowRect))
+        if (!mNativeWindow.getClientRect(&windowRect))
         {
             ASSERT(false);
 
-            ERR("Could not retrieve the window dimensions");
-            return error(EGL_BAD_SURFACE, false);
+            return Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions");
         }
 
         width = windowRect.right - windowRect.left;
         height = windowRect.bottom - windowRect.top;
     }
     else
-#endif
     {
         // non-window surface - size is determined at creation
         width = mWidth;
         height = mHeight;
     }
 
-    mSwapChain = mRenderer->createSwapChain(mWindow, mShareHandle,
+    mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle,
                                             mConfig->mRenderTargetFormat,
                                             mConfig->mDepthStencilFormat);
     if (!mSwapChain)
     {
-        return error(EGL_BAD_ALLOC, false);
+        return Error(EGL_BAD_ALLOC);
     }
 
-    if (!resetSwapChain(width, height))
+    Error error = resetSwapChain(width, height);
+    if (error.isError())
     {
-        delete mSwapChain;
-        mSwapChain = NULL;
-        return false;
+        SafeDelete(mSwapChain);
+        return error;
     }
 
-    return true;
+    return Error(EGL_SUCCESS);
 }
 
-bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight)
+Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight)
 {
-    ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
     ASSERT(mSwapChain);
 
-    EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight));
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+    backbufferWidth = std::max(1, backbufferWidth);
+    backbufferHeight = std::max(1, backbufferHeight);
+#endif
+    EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight);
 
     if (status == EGL_CONTEXT_LOST)
     {
         mDisplay->notifyDeviceLost();
-        return false;
+        return Error(status);
     }
     else if (status != EGL_SUCCESS)
     {
-        return error(status, false);
+        return Error(status);
     }
 
     mWidth = backbufferWidth;
     mHeight = backbufferHeight;
 
-    return true;
+    return Error(EGL_SUCCESS);
 }
 
-bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
+Error Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
 {
     ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
     ASSERT(mSwapChain);
@@ -269,69 +195,71 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
     if (status == EGL_CONTEXT_LOST)
     {
         mRenderer->notifyDeviceLost();
-        return false;
+        return Error(status);
     }
     else if (status != EGL_SUCCESS)
     {
-        return error(status, false);
+        return Error(status);
     }
 
     mWidth = backbufferWidth;
     mHeight = backbufferHeight;
     mSwapIntervalDirty = false;
 
-    return true;
+    return Error(EGL_SUCCESS);
 }
 
-bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
 {
     if (!mSwapChain)
     {
-        return true;
+        return Error(EGL_SUCCESS);
     }
 
-    if (x + width > mWidth)
+    if (x + width > abs(mWidth))
     {
-        width = mWidth - x;
+        width = abs(mWidth) - x;
     }
 
-    if (y + height > mHeight)
+    if (y + height > abs(mHeight))
     {
-        height = mHeight - y;
+        height = abs(mHeight) - y;
     }
 
     if (width == 0 || height == 0)
     {
-        return true;
+        return Error(EGL_SUCCESS);
     }
 
-    EGLint status = mSwapChain->swapRect(x, y, width, height, mSwapFlags);
+    ASSERT(width > 0);
+    ASSERT(height > 0);
+
+    EGLint status = mSwapChain->swapRect(x, y, width, height);
 
     if (status == EGL_CONTEXT_LOST)
     {
         mRenderer->notifyDeviceLost();
-        return false;
+        return Error(status);
     }
     else if (status != EGL_SUCCESS)
     {
-        return error(status, false);
+        return Error(status);
     }
 
     checkForOutOfDateSwapChain();
 
-    return true;
+    return Error(EGL_SUCCESS);
 }
 
 EGLNativeWindowType Surface::getWindowHandle()
 {
-    return mWindow;
+    return mNativeWindow.getNativeWindow();
 }
 
-
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
 #define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
 #define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
 
-#if !defined(ANGLE_PLATFORM_WINRT)
 static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
 {
   if (message == WM_SIZE)
@@ -349,45 +277,50 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam
 
 void Surface::subclassWindow()
 {
-#if !defined(ANGLE_PLATFORM_WINRT)
-    if (!mWindow)
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+    HWND window = mNativeWindow.getNativeWindow();
+    if (!window)
     {
         return;
     }
 
     DWORD processId;
-    DWORD threadId = GetWindowThreadProcessId(mWindow, &processId);
+    DWORD threadId = GetWindowThreadProcessId(window, &processId);
     if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
     {
         return;
     }
 
     SetLastError(0);
-    LONG_PTR oldWndProc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
+    LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
     if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
     {
         mWindowSubclassed = false;
         return;
     }
 
-    SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
-    SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
+    SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
+    SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
     mWindowSubclassed = true;
-#else
-    mWindowSubclassed = false;
 #endif
 }
 
 void Surface::unsubclassWindow()
 {
-#if !defined(ANGLE_PLATFORM_WINRT)
     if(!mWindowSubclassed)
     {
         return;
     }
 
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+    HWND window = mNativeWindow.getNativeWindow();
+    if (!window)
+    {
+        return;
+    }
+
     // un-subclass
-    LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(mWindow, kParentWndProc));
+    LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, kParentWndProc));
 
     // Check the windowproc is still SurfaceWindowProc.
     // If this assert fails, then it is likely the application has subclassed the
@@ -396,29 +329,28 @@ void Surface::unsubclassWindow()
     // EGL context, or to unsubclass before destroying the EGL context.
     if(parentWndFunc)
     {
-        LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc);
+        LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc);
         UNUSED_ASSERTION_VARIABLE(prevWndFunc);
         ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
     }
 
-    RemoveProp(mWindow, kSurfaceProperty);
-    RemoveProp(mWindow, kParentWndProc);
-    mWindowSubclassed = false;
+    RemoveProp(window, kSurfaceProperty);
+    RemoveProp(window, kParentWndProc);
 #endif
+    mWindowSubclassed = false;
 }
 
 bool Surface::checkForOutOfDateSwapChain()
 {
+    RECT client;
     int clientWidth = getWidth();
     int clientHeight = getHeight();
     bool sizeDirty = false;
-#if !defined(ANGLE_PLATFORM_WINRT)
-    if (!mFixedSize && !IsIconic(getWindowHandle()))
+    if (!mFixedSize && !mNativeWindow.isIconic())
     {
-        RECT client;
         // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized
         // because that's not a useful size to render to.
-        if (!GetClientRect(getWindowHandle(), &client))
+        if (!mNativeWindow.getClientRect(&client))
         {
             ASSERT(false);
             return false;
@@ -429,7 +361,13 @@ bool Surface::checkForOutOfDateSwapChain()
         clientHeight = client.bottom - client.top;
         sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
     }
-#endif
+
+    if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight))
+    {
+        clientWidth = mFixedWidth;
+        clientHeight = mFixedHeight;
+        sizeDirty = true;
+    }
 
     bool wasDirty = (mSwapIntervalDirty || sizeDirty);
 
@@ -455,17 +393,17 @@ bool Surface::checkForOutOfDateSwapChain()
     return false;
 }
 
-bool Surface::swap()
+Error Surface::swap()
 {
-    return swapRect(0, 0, mWidth, mHeight);
+    return swapRect(0, 0, abs(mWidth), abs(mHeight));
 }
 
-bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
 {
     if (!mPostSubBufferSupported)
     {
         // Spec is not clear about how this should be handled.
-        return true;
+        return Error(EGL_SUCCESS);
     }
 
     return swapRect(x, y, width, height);
@@ -550,77 +488,18 @@ EGLint Surface::isFixedSize() const
     return mFixedSize;
 }
 
-EGLenum Surface::getFormat() const
+void Surface::setFixedWidth(EGLint width)
 {
-    return mConfig->mRenderTargetFormat;
+    mFixedWidth = width;
 }
 
-#if defined(ANGLE_PLATFORM_WINRT)
-
-HRESULT Surface::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *args)
+void Surface::setFixedHeight(EGLint height)
 {
-    HRESULT hr;
-    Size size;
-    hr = args->get_Size(&size);
-    ASSERT(SUCCEEDED(hr));
-
-    resizeSwapChain(std::floor(size.Width * mScaleFactor + 0.5),
-                    std::floor(size.Height * mScaleFactor + 0.5));
-
-    if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
-    {
-        glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
-    }
-
-    return S_OK;
-}
-
-HRESULT Surface::onDpiChanged(IDisplayInformation *displayInformation, IInspectable *)
-{
-    HRESULT hr;
-#   if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-    ComPtr<IDisplayInformation2> displayInformation2;
-    hr = displayInformation->QueryInterface(displayInformation2.GetAddressOf());
-    ASSERT(SUCCEEDED(hr));
-
-    hr = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor);
-    ASSERT(SUCCEEDED(hr));
-#   else
-    ResolutionScale resolutionScale;
-    hr = displayInformation->get_ResolutionScale(&resolutionScale);
-    ASSERT(SUCCEEDED(hr));
-
-    mScaleFactor = double(resolutionScale) / 100.0;
-#   endif
-    return S_OK;
-}
-
-#   if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
-HRESULT Surface::onOrientationChanged(IDisplayInformation *displayInformation, IInspectable *)
-{
-    HRESULT hr;
-    DisplayOrientations orientation;
-    hr = displayInformation->get_CurrentOrientation(&orientation);
-    ASSERT(SUCCEEDED(hr));
-    switch (orientation) {
-    default:
-    case DisplayOrientations_Portrait:
-        mSwapFlags = rx::SWAP_NORMAL;
-        break;
-    case DisplayOrientations_Landscape:
-        mSwapFlags = rx::SWAP_ROTATE_90;
-        break;
-    case DisplayOrientations_LandscapeFlipped:
-        mSwapFlags = rx::SWAP_ROTATE_270;
-        break;
-    case DisplayOrientations_PortraitFlipped:
-        mSwapFlags = rx::SWAP_ROTATE_180;
-        break;
-    }
-    return S_OK;
+    mFixedHeight = height;
 }
-#   endif
-
-#endif
 
+EGLenum Surface::getFormat() const
+{
+    return mConfig->mRenderTargetFormat;
+}
 }
diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h
index ebffce8fed6..46382d06e1f 100644
--- a/src/3rdparty/angle/src/libEGL/Surface.h
+++ b/src/3rdparty/angle/src/libEGL/Surface.h
@@ -11,23 +11,12 @@
 #ifndef LIBEGL_SURFACE_H_
 #define LIBEGL_SURFACE_H_
 
+#include "libEGL/Error.h"
+
 #include <EGL/egl.h>
 
 #include "common/angleutils.h"
-
-#if defined(ANGLE_PLATFORM_WINRT)
-#include <EventToken.h>
-namespace ABI { namespace Windows {
-    namespace UI { namespace Core {
-        struct ICoreWindow;
-        struct IWindowSizeChangedEventArgs;
-    } }
-    namespace Graphics { namespace Display {
-        struct IDisplayInformation;
-    } }
-} }
-struct IInspectable;
-#endif
+#include "common/NativeWindow.h"
 
 namespace gl
 {
@@ -35,8 +24,8 @@ class Texture2D;
 }
 namespace rx
 {
-class Renderer;
 class SwapChain;
+class RendererD3D; //TODO(jmadill): remove this
 }
 
 namespace egl
@@ -52,13 +41,13 @@ class Surface
 
     virtual ~Surface();
 
-    bool initialize();
+    Error initialize();
     void release();
-    bool resetSwapChain();
+    Error resetSwapChain();
 
     EGLNativeWindowType getWindowHandle();
-    bool swap();
-    bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
+    Error swap();
+    Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
 
     virtual EGLint isPostSubBufferSupported() const;
 
@@ -81,35 +70,31 @@ class Surface
     virtual gl::Texture2D *getBoundTexture() const;
 
     EGLint isFixedSize() const;
+    void setFixedWidth(EGLint width);
+    void setFixedHeight(EGLint height);
 
-private:
+  private:
     DISALLOW_COPY_AND_ASSIGN(Surface);
 
-#if defined(ANGLE_PLATFORM_WINRT)
-    HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
-    HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
-#   if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-    HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
-#   endif
-#endif
-
     Display *const mDisplay;
-    rx::Renderer *mRenderer;
+    rx::RendererD3D *mRenderer;
 
     HANDLE mShareHandle;
     rx::SwapChain *mSwapChain;
 
     void subclassWindow();
     void unsubclassWindow();
-    bool resizeSwapChain(int backbufferWidth, int backbufferHeight);
-    bool resetSwapChain(int backbufferWidth, int backbufferHeight);
-    bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
+    Error resizeSwapChain(int backbufferWidth, int backbufferHeight);
+    Error resetSwapChain(int backbufferWidth, int backbufferHeight);
+    Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
 
-    const EGLNativeWindowType mWindow;            // Window that the surface is created for.
+    rx::NativeWindow mNativeWindow;   // Handler for the Window that the surface is created for.
     bool mWindowSubclassed;        // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
     const egl::Config *mConfig;    // EGL config surface was created with
     EGLint mHeight;                // Height of surface
     EGLint mWidth;                 // Width of surface
+    EGLint mFixedHeight;         // Pending height of the surface
+    EGLint mFixedWidth;          // Pending width of the surface
 //  EGLint horizontalResolution;   // Horizontal dot pitch
 //  EGLint verticalResolution;     // Vertical dot pitch
 //  EGLBoolean largestPBuffer;     // If true, create largest pbuffer possible
@@ -126,18 +111,9 @@ private:
     EGLint mSwapInterval;
     EGLint mPostSubBufferSupported;
     EGLint mFixedSize;
-    EGLint mSwapFlags;
 
     bool mSwapIntervalDirty;
     gl::Texture2D *mTexture;
-#if defined(ANGLE_PLATFORM_WINRT)
-    double mScaleFactor;
-    EventRegistrationToken mSizeToken;
-    EventRegistrationToken mDpiToken;
-#   if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-    EventRegistrationToken mOrientationToken;
-#   endif
-#endif
 };
 }
 
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp
index c2e0fd6d3d8..68399d63a4b 100644
--- a/src/3rdparty/angle/src/libEGL/libEGL.cpp
+++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp
@@ -13,7 +13,6 @@
 
 #include "common/debug.h"
 #include "common/version.h"
-#include "common/platform.h"
 #include "libGLESv2/Context.h"
 #include "libGLESv2/Texture.h"
 #include "libGLESv2/main.h"
@@ -26,16 +25,20 @@
 #include "libEGL/Display.h"
 #include "libEGL/Surface.h"
 
+#include "common/NativeWindow.h"
+
 bool validateDisplay(egl::Display *display)
 {
     if (display == EGL_NO_DISPLAY)
     {
-        return egl::error(EGL_BAD_DISPLAY, false);
+        recordError(egl::Error(EGL_BAD_DISPLAY));
+        return false;
     }
 
     if (!display->isInitialized())
     {
-        return egl::error(EGL_NOT_INITIALIZED, false);
+        recordError(egl::Error(EGL_NOT_INITIALIZED));
+        return false;
     }
 
     return true;
@@ -50,7 +53,8 @@ bool validateConfig(egl::Display *display, EGLConfig config)
 
     if (!display->isValidConfig(config))
     {
-        return egl::error(EGL_BAD_CONFIG, false);
+        recordError(egl::Error(EGL_BAD_CONFIG));
+        return false;
     }
 
     return true;
@@ -65,7 +69,8 @@ bool validateContext(egl::Display *display, gl::Context *context)
 
     if (!display->isValidContext(context))
     {
-        return egl::error(EGL_BAD_CONTEXT, false);
+        recordError(egl::Error(EGL_BAD_CONTEXT));
+        return false;
     }
 
     return true;
@@ -80,7 +85,8 @@ bool validateSurface(egl::Display *display, egl::Surface *surface)
 
     if (!display->isValidSurface(surface))
     {
-        return egl::error(EGL_BAD_SURFACE, false);
+        recordError(egl::Error(EGL_BAD_SURFACE));
+        return false;
     }
 
     return true;
@@ -93,12 +99,7 @@ EGLint __stdcall eglGetError(void)
     EVENT("()");
 
     EGLint error = egl::getCurrentError();
-
-    if (error != EGL_SUCCESS)
-    {
-        egl::setCurrentError(EGL_SUCCESS);
-    }
-
+    recordError(egl::Error(EGL_SUCCESS));
     return error;
 }
 
@@ -106,7 +107,7 @@ EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id)
 {
     EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
 
-    return egl::Display::getDisplay(display_id, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+    return egl::Display::getDisplay(display_id, egl::AttributeMap());
 }
 
 EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
@@ -120,19 +121,26 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis
         break;
 
       default:
-        return egl::error(EGL_BAD_CONFIG, EGL_NO_DISPLAY);
+        recordError(egl::Error(EGL_BAD_CONFIG));
+        return EGL_NO_DISPLAY;
     }
 
     EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display);
-#if !defined(ANGLE_PLATFORM_WINRT)
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
     // Validate the display device context
     if (WindowFromDC(displayId) == NULL)
     {
-        return egl::success(EGL_NO_DISPLAY);
+        recordError(egl::Error(EGL_SUCCESS));
+        return EGL_NO_DISPLAY;
     }
 #endif
 
-    EGLint requestedDisplayType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
+    EGLint platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
+    bool majorVersionSpecified = false;
+    bool minorVersionSpecified = false;
+    bool requestedWARP = false;
+
     if (attrib_list)
     {
         for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
@@ -140,7 +148,69 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis
             switch (curAttrib[0])
             {
               case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
-                requestedDisplayType = curAttrib[1];
+                switch (curAttrib[1])
+                {
+                  case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+                    break;
+
+                  case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+                  case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+                    if (!egl::Display::supportsPlatformD3D())
+                    {
+                        recordError(egl::Error(EGL_SUCCESS));
+                        return EGL_NO_DISPLAY;
+                    }
+                    break;
+
+                  case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+                  case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+                    if (!egl::Display::supportsPlatformOpenGL())
+                    {
+                        recordError(egl::Error(EGL_SUCCESS));
+                        return EGL_NO_DISPLAY;
+                    }
+                    break;
+
+                  default:
+                    recordError(egl::Error(EGL_SUCCESS));
+                    return EGL_NO_DISPLAY;
+                }
+                platformType = curAttrib[1];
+                break;
+
+              case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
+                if (curAttrib[1] != EGL_DONT_CARE)
+                {
+                    majorVersionSpecified = true;
+                }
+                break;
+
+              case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
+                if (curAttrib[1] != EGL_DONT_CARE)
+                {
+                    minorVersionSpecified = true;
+                }
+                break;
+
+              case EGL_PLATFORM_ANGLE_USE_WARP_ANGLE:
+                if (!egl::Display::supportsPlatformD3D())
+                {
+                    recordError(egl::Error(EGL_SUCCESS));
+                    return EGL_NO_DISPLAY;
+                }
+
+                switch (curAttrib[1])
+                {
+                  case EGL_FALSE:
+                  case EGL_TRUE:
+                    break;
+
+                  default:
+                    recordError(egl::Error(EGL_SUCCESS));
+                    return EGL_NO_DISPLAY;
+                }
+
+                requestedWARP = (curAttrib[1] == EGL_TRUE);
                 break;
 
               default:
@@ -149,33 +219,20 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis
         }
     }
 
-    switch (requestedDisplayType)
+    if (!majorVersionSpecified && minorVersionSpecified)
     {
-      case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
-        break;
-
-      case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
-      case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
-      case EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE:
-        if (!egl::Display::supportsPlatformD3D())
-        {
-            return egl::success(EGL_NO_DISPLAY);
-        }
-        break;
-
-      case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
-      case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
-        if (!egl::Display::supportsPlatformOpenGL())
-        {
-            return egl::success(EGL_NO_DISPLAY);
-        }
-        break;
+        recordError(egl::Error(EGL_BAD_ATTRIBUTE));
+        return EGL_NO_DISPLAY;
+    }
 
-      default:
-        return egl::success(EGL_NO_DISPLAY);
+    if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE && requestedWARP)
+    {
+        recordError(egl::Error(EGL_BAD_ATTRIBUTE));
+        return EGL_NO_DISPLAY;
     }
 
-    return egl::Display::getDisplay(displayId, requestedDisplayType);
+    recordError(egl::Error(EGL_SUCCESS));
+    return egl::Display::getDisplay(displayId, egl::AttributeMap(attrib_list));
 }
 
 EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
@@ -185,20 +242,24 @@ EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
 
     if (dpy == EGL_NO_DISPLAY)
     {
-        return egl::error(EGL_BAD_DISPLAY, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_DISPLAY));
+        return EGL_FALSE;
     }
 
     egl::Display *display = static_cast<egl::Display*>(dpy);
 
-    if (!display->initialize())
+    egl::Error error = display->initialize();
+    if (error.isError())
     {
-        return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE);
+        recordError(error);
+        return EGL_FALSE;
     }
 
     if (major) *major = 1;
     if (minor) *minor = 4;
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
@@ -207,14 +268,16 @@ EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
 
     if (dpy == EGL_NO_DISPLAY)
     {
-        return egl::error(EGL_BAD_DISPLAY, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_DISPLAY));
+        return EGL_FALSE;
     }
 
     egl::Display *display = static_cast<egl::Display*>(dpy);
 
     display->terminate();
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
@@ -227,19 +290,28 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
         return NULL;
     }
 
+    const char *result;
     switch (name)
     {
       case EGL_CLIENT_APIS:
-        return egl::success("OpenGL_ES");
+        result = "OpenGL_ES";
+        break;
       case EGL_EXTENSIONS:
-        return egl::success(egl::Display::getExtensionString(display));
+        result = egl::Display::getExtensionString(display);
+        break;
       case EGL_VENDOR:
-        return egl::success(display->getVendorString());
+        result = display->getVendorString();
+        break;
       case EGL_VERSION:
-        return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")");
+        result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")";
+        break;
       default:
-        return egl::error(EGL_BAD_PARAMETER, (const char*)NULL);
+        recordError(egl::Error(EGL_BAD_PARAMETER));
+        return NULL;
     }
+
+    recordError(egl::Error(EGL_SUCCESS));
+    return result;
 }
 
 EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
@@ -257,17 +329,20 @@ EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint co
 
     if (!num_config)
     {
-        return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_PARAMETER));
+        return EGL_FALSE;
     }
 
     const EGLint attribList[] =    {EGL_NONE};
 
     if (!display->getConfigs(configs, attribList, config_size, num_config))
     {
-        return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_ATTRIBUTE));
+        return EGL_FALSE;
     }
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
@@ -285,7 +360,8 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
 
     if (!num_config)
     {
-        return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_PARAMETER));
+        return EGL_FALSE;
     }
 
     const EGLint attribList[] =    {EGL_NONE};
@@ -297,7 +373,8 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
 
     display->getConfigs(configs, attrib_list, config_size, num_config);
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
@@ -314,10 +391,12 @@ EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint
 
     if (!display->getConfigAttrib(config, attribute, value))
     {
-        return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_ATTRIBUTE));
+        return EGL_FALSE;
     }
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
@@ -332,16 +411,21 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG
         return EGL_NO_SURFACE;
     }
 
-#if !defined(ANGLE_PLATFORM_WINRT)
-    HWND window = (HWND)win;
+    if (!rx::IsValidEGLNativeWindowType(win))
+    {
+        recordError(egl::Error(EGL_BAD_NATIVE_WINDOW));
+        return EGL_NO_SURFACE;
+    }
 
-    if (!IsWindow(window))
+    EGLSurface surface = EGL_NO_SURFACE;
+    egl::Error error = display->createWindowSurface(win, config, attrib_list, &surface);
+    if (error.isError())
     {
-        return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+        recordError(error);
+        return EGL_NO_SURFACE;
     }
-#endif
 
-    return display->createWindowSurface(win, config, attrib_list);
+    return surface;
 }
 
 EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
@@ -356,7 +440,15 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c
         return EGL_NO_SURFACE;
     }
 
-    return display->createOffscreenSurface(config, NULL, attrib_list);
+    EGLSurface surface = EGL_NO_SURFACE;
+    egl::Error error = display->createOffscreenSurface(config, NULL, attrib_list, &surface);
+    if (error.isError())
+    {
+        recordError(error);
+        return EGL_NO_SURFACE;
+    }
+
+    return surface;
 }
 
 EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
@@ -373,7 +465,8 @@ EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EG
 
     UNIMPLEMENTED();   // FIXME
 
-    return egl::success(EGL_NO_SURFACE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_NO_SURFACE;
 }
 
 EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
@@ -390,12 +483,14 @@ EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
 
     if (surface == EGL_NO_SURFACE)
     {
-        return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
     }
 
     display->destroySurface((egl::Surface*)surface);
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
@@ -413,7 +508,8 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint
 
     if (surface == EGL_NO_SURFACE)
     {
-        return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
     }
 
     switch (attribute)
@@ -473,10 +569,12 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint
         *value = eglSurface->isFixedSize();
         break;
       default:
-        return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_ATTRIBUTE));
+        return EGL_FALSE;
     }
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
@@ -498,7 +596,8 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
 
             if (surface == EGL_NO_SURFACE)
             {
-                return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
+                recordError(egl::Error(EGL_BAD_SURFACE));
+                return EGL_FALSE;
             }
 
             rx::SwapChain *swapchain = eglSurface->getSwapChain();
@@ -522,7 +621,8 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
 
             if (renderer->getMajorShaderModel() < 4)
             {
-                return egl::error(EGL_BAD_CONTEXT, EGL_FALSE);
+                recordError(egl::Error(EGL_BAD_CONTEXT));
+                return EGL_FALSE;
             }
 
             *value = static_cast<rx::Renderer11*>(renderer)->getDevice();
@@ -530,10 +630,12 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
         break;
 #endif
       default:
-        return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_ATTRIBUTE));
+        return EGL_FALSE;
     }
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLBoolean __stdcall eglBindAPI(EGLenum api)
@@ -544,16 +646,19 @@ EGLBoolean __stdcall eglBindAPI(EGLenum api)
     {
       case EGL_OPENGL_API:
       case EGL_OPENVG_API:
-        return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation
+        recordError(egl::Error(EGL_BAD_PARAMETER));
+        return EGL_FALSE;   // Not supported by this implementation
       case EGL_OPENGL_ES_API:
         break;
       default:
-        return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_PARAMETER));
+        return EGL_FALSE;
     }
 
     egl::setCurrentAPI(api);
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLenum __stdcall eglQueryAPI(void)
@@ -562,7 +667,8 @@ EGLenum __stdcall eglQueryAPI(void)
 
     EGLenum API = egl::getCurrentAPI();
 
-    return egl::success(API);
+    recordError(egl::Error(EGL_SUCCESS));
+    return API;
 }
 
 EGLBoolean __stdcall eglWaitClient(void)
@@ -571,7 +677,8 @@ EGLBoolean __stdcall eglWaitClient(void)
 
     UNIMPLEMENTED();   // FIXME
 
-    return egl::success(0);
+    recordError(egl::Error(EGL_SUCCESS));
+    return 0;
 }
 
 EGLBoolean __stdcall eglReleaseThread(void)
@@ -580,7 +687,8 @@ EGLBoolean __stdcall eglReleaseThread(void)
 
     eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
@@ -598,10 +706,19 @@ EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum bu
 
     if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer)
     {
-        return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+        recordError(egl::Error(EGL_BAD_PARAMETER));
+        return EGL_NO_SURFACE;
+    }
+
+    EGLSurface surface = EGL_NO_SURFACE;
+    egl::Error error = display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list, &surface);
+    if (error.isError())
+    {
+        recordError(error);
+        return EGL_NO_SURFACE;
     }
 
-    return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list);
+    return surface;
 }
 
 EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
@@ -617,9 +734,30 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint
         return EGL_FALSE;
     }
 
+    switch (attribute)
+    {
+    case EGL_WIDTH:
+        if (!eglSurface->isFixedSize() || !value) {
+            recordError(egl::Error(EGL_BAD_PARAMETER));
+            return EGL_FALSE;
+        }
+        eglSurface->setFixedWidth(value);
+        return EGL_TRUE;
+    case EGL_HEIGHT:
+        if (!eglSurface->isFixedSize() || !value) {
+            recordError(egl::Error(EGL_BAD_PARAMETER));
+            return EGL_FALSE;
+        }
+        eglSurface->setFixedHeight(value);
+        return EGL_TRUE;
+    default:
+        break;
+    }
+
     UNIMPLEMENTED();   // FIXME
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
@@ -636,30 +774,36 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint
 
     if (buffer != EGL_BACK_BUFFER)
     {
-        return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_PARAMETER));
+        return EGL_FALSE;
     }
 
     if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
     {
-        return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
     }
 
     if (eglSurface->getBoundTexture())
     {
-        return egl::error(EGL_BAD_ACCESS, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_ACCESS));
+        return EGL_FALSE;
     }
 
     if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
     {
-        return egl::error(EGL_BAD_MATCH, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_MATCH));
+        return EGL_FALSE;
     }
 
     if (!glBindTexImage(eglSurface))
     {
-        return egl::error(EGL_BAD_MATCH, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_MATCH));
+        return EGL_FALSE;
     }
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
@@ -676,17 +820,20 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi
 
     if (buffer != EGL_BACK_BUFFER)
     {
-        return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_PARAMETER));
+        return EGL_FALSE;
     }
 
     if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
     {
-        return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
     }
 
     if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
     {
-        return egl::error(EGL_BAD_MATCH, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_MATCH));
+        return EGL_FALSE;
     }
 
     gl::Texture2D *texture = eglSurface->getBoundTexture();
@@ -696,7 +843,8 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi
         texture->releaseTexImage();
     }
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
@@ -714,12 +862,14 @@ EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
 
     if (draw_surface == NULL)
     {
-        return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
     }
 
     draw_surface->setSwapInterval(interval);
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
@@ -744,27 +894,38 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
               case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
                 if (attribute[1] == EGL_TRUE)
                 {
-                    return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);   // Unimplemented
+                    recordError(egl::Error(EGL_BAD_CONFIG));   // Unimplemented
+                    return EGL_NO_CONTEXT;
                     // robust_access = true;
                 }
                 else if (attribute[1] != EGL_FALSE)
-                    return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                {
+                    recordError(egl::Error(EGL_BAD_ATTRIBUTE));
+                    return EGL_NO_CONTEXT;
+                }
                 break;
               case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
                 if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
+                {
                     reset_notification = true;
+                }
                 else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
-                    return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                {
+                    recordError(egl::Error(EGL_BAD_ATTRIBUTE));
+                    return EGL_NO_CONTEXT;
+                }
                 break;
               default:
-                return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
+                recordError(egl::Error(EGL_BAD_ATTRIBUTE));
+                return EGL_NO_CONTEXT;
             }
         }
     }
 
     if (client_version != 2 && client_version != 3)
     {
-        return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
+        recordError(egl::Error(EGL_BAD_CONFIG));
+        return EGL_NO_CONTEXT;
     }
 
     egl::Display *display = static_cast<egl::Display*>(dpy);
@@ -775,18 +936,21 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
 
         if (sharedGLContext->isResetNotificationEnabled() != reset_notification)
         {
-            return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
+            recordError(egl::Error(EGL_BAD_MATCH));
+            return EGL_NO_CONTEXT;
         }
 
         if (sharedGLContext->getClientVersion() != client_version)
         {
-            return egl::error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
+            recordError(egl::Error(EGL_BAD_CONTEXT));
+            return EGL_NO_CONTEXT;
         }
 
         // Can not share contexts between displays
         if (sharedGLContext->getRenderer() != display->getRenderer())
         {
-            return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
+            recordError(egl::Error(EGL_BAD_MATCH));
+            return EGL_NO_CONTEXT;
         }
     }
 
@@ -795,7 +959,16 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
         return EGL_NO_CONTEXT;
     }
 
-    return display->createContext(config, client_version, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
+    EGLContext context = EGL_NO_CONTEXT;
+    egl::Error error =  display->createContext(config, client_version, static_cast<gl::Context*>(share_context),
+                                               reset_notification, robust_access, &context);
+    if (error.isError())
+    {
+        recordError(error);
+        return EGL_NO_CONTEXT;
+    }
+
+    return context;
 }
 
 EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
@@ -812,12 +985,14 @@ EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
 
     if (ctx == EGL_NO_CONTEXT)
     {
-        return egl::error(EGL_BAD_CONTEXT, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_CONTEXT));
+        return EGL_FALSE;
     }
 
     display->destroyContext(context);
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
@@ -832,7 +1007,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
     bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE);
     if (noContext != noSurface)
     {
-        return egl::error(EGL_BAD_MATCH, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_MATCH));
+        return EGL_FALSE;
     }
 
     if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
@@ -850,7 +1026,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
 
         if (renderer->isDeviceLost())
         {
-            return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
+            recordError(egl::Error(EGL_CONTEXT_LOST));
+            return EGL_FALSE;
         }
     }
 
@@ -871,7 +1048,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
 
     glMakeCurrent(context, display, static_cast<egl::Surface*>(draw));
 
-    return egl::success(EGL_TRUE);
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLContext __stdcall eglGetCurrentContext(void)
@@ -880,7 +1058,8 @@ EGLContext __stdcall eglGetCurrentContext(void)
 
     EGLContext context = glGetCurrentContext();
 
-    return egl::success(context);
+    recordError(egl::Error(EGL_SUCCESS));
+    return context;
 }
 
 EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
@@ -889,17 +1068,18 @@ EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
 
     if (readdraw == EGL_READ)
     {
-        EGLSurface read = egl::getCurrentReadSurface();
-        return egl::success(read);
+        recordError(egl::Error(EGL_SUCCESS));
+        return egl::getCurrentReadSurface();
     }
     else if (readdraw == EGL_DRAW)
     {
-        EGLSurface draw = egl::getCurrentDrawSurface();
-        return egl::success(draw);
+        recordError(egl::Error(EGL_SUCCESS));
+        return egl::getCurrentDrawSurface();
     }
     else
     {
-        return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
+        recordError(egl::Error(EGL_BAD_PARAMETER));
+        return EGL_NO_SURFACE;
     }
 }
 
@@ -909,7 +1089,8 @@ EGLDisplay __stdcall eglGetCurrentDisplay(void)
 
     EGLDisplay dpy = egl::getCurrentDisplay();
 
-    return egl::success(dpy);
+    recordError(egl::Error(EGL_SUCCESS));
+    return dpy;
 }
 
 EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
@@ -927,7 +1108,8 @@ EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attr
 
     UNIMPLEMENTED();   // FIXME
 
-    return egl::success(0);
+    recordError(egl::Error(EGL_SUCCESS));
+    return 0;
 }
 
 EGLBoolean __stdcall eglWaitGL(void)
@@ -936,7 +1118,8 @@ EGLBoolean __stdcall eglWaitGL(void)
 
     UNIMPLEMENTED();   // FIXME
 
-    return egl::success(0);
+    recordError(egl::Error(EGL_SUCCESS));
+    return 0;
 }
 
 EGLBoolean __stdcall eglWaitNative(EGLint engine)
@@ -945,7 +1128,8 @@ EGLBoolean __stdcall eglWaitNative(EGLint engine)
 
     UNIMPLEMENTED();   // FIXME
 
-    return egl::success(0);
+    recordError(egl::Error(EGL_SUCCESS));
+    return 0;
 }
 
 EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
@@ -962,20 +1146,25 @@ EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
 
     if (display->getRenderer()->isDeviceLost())
     {
-        return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
+        recordError(egl::Error(EGL_CONTEXT_LOST));
+        return EGL_FALSE;
     }
 
     if (surface == EGL_NO_SURFACE)
     {
-        return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
     }
 
-    if (eglSurface->swap())
+    egl::Error error = eglSurface->swap();
+    if (error.isError())
     {
-        return egl::success(EGL_TRUE);
+        recordError(error);
+        return EGL_FALSE;
     }
 
-    return EGL_FALSE;
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
@@ -992,12 +1181,14 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ
 
     if (display->getRenderer()->isDeviceLost())
     {
-        return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
+        recordError(egl::Error(EGL_CONTEXT_LOST));
+        return EGL_FALSE;
     }
 
     UNIMPLEMENTED();   // FIXME
 
-    return egl::success(0);
+    recordError(egl::Error(EGL_SUCCESS));
+    return 0;
 }
 
 EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
@@ -1006,7 +1197,8 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi
 
     if (x < 0 || y < 0 || width < 0 || height < 0)
     {
-        return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_PARAMETER));
+        return EGL_FALSE;
     }
 
     egl::Display *display = static_cast<egl::Display*>(dpy);
@@ -1019,20 +1211,25 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi
 
     if (display->getRenderer()->isDeviceLost())
     {
-        return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
+        recordError(egl::Error(EGL_CONTEXT_LOST));
+        return EGL_FALSE;
     }
 
     if (surface == EGL_NO_SURFACE)
     {
-        return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
+        recordError(egl::Error(EGL_BAD_SURFACE));
+        return EGL_FALSE;
     }
 
-    if (eglSurface->postSubBuffer(x, y, width, height))
+    egl::Error error = eglSurface->postSubBuffer(x, y, width, height);
+    if (error.isError())
     {
-        return egl::success(EGL_TRUE);
+        recordError(error);
+        return EGL_FALSE;
     }
 
-    return EGL_FALSE;
+    recordError(egl::Error(EGL_SUCCESS));
+    return EGL_TRUE;
 }
 
 __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)
diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp
index e74737eabaa..e88cad775f9 100644
--- a/src/3rdparty/angle/src/libEGL/main.cpp
+++ b/src/3rdparty/angle/src/libEGL/main.cpp
@@ -11,9 +11,6 @@
 #include "common/debug.h"
 #include "common/tls.h"
 
-#if defined(ANGLE_PLATFORM_WINRT)
-__declspec(thread)
-#endif
 static TLSIndex currentTLS = TLS_OUT_OF_INDEXES;
 
 namespace egl
@@ -21,12 +18,6 @@ namespace egl
 
 Current *AllocateCurrent()
 {
-#if defined(ANGLE_PLATFORM_WINRT)
-    if (currentTLS == TLS_OUT_OF_INDEXES)
-    {
-        currentTLS = CreateTLSIndex();
-    }
-#endif
     ASSERT(currentTLS != TLS_OUT_OF_INDEXES);
     if (currentTLS == TLS_OUT_OF_INDEXES)
     {
@@ -51,12 +42,6 @@ Current *AllocateCurrent()
 
 void DeallocateCurrent()
 {
-#if defined(ANGLE_PLATFORM_WINRT)
-    if (currentTLS == TLS_OUT_OF_INDEXES)
-    {
-        return;
-    }
-#endif
     Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
     SafeDelete(current);
     SetTLSValue(currentTLS, NULL);
@@ -72,7 +57,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
     {
       case DLL_PROCESS_ATTACH:
         {
-#if defined(ANGLE_ENABLE_TRACE)
+#if defined(ANGLE_ENABLE_DEBUG_TRACE)
             FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");
 
             if (debug)
@@ -87,15 +72,15 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
             }
 #endif
 
-#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain
-            return DisableThreadLibraryCalls(instance);
-#endif
-
             currentTLS = CreateTLSIndex();
             if (currentTLS == TLS_OUT_OF_INDEXES)
             {
                 return FALSE;
             }
+
+#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
+            gl::InitializeDebugAnnotations();
+#endif
         }
         // Fall through to initialize index
       case DLL_THREAD_ATTACH:
@@ -105,15 +90,17 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
         break;
       case DLL_THREAD_DETACH:
         {
-#if !defined(ANGLE_PLATFORM_WINRT)
             egl::DeallocateCurrent();
-#endif
         }
         break;
       case DLL_PROCESS_DETACH:
         {
             egl::DeallocateCurrent();
             DestroyTLSIndex(currentTLS);
+
+#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
+            gl::UninitializeDebugAnnotations();
+#endif
         }
         break;
       default:
@@ -143,11 +130,11 @@ Current *GetCurrentData()
 #endif
 }
 
-void setCurrentError(EGLint error)
+void recordError(const Error &error)
 {
     Current *current = GetCurrentData();
 
-    current->error = error;
+    current->error = error.getCode();
 }
 
 EGLint getCurrentError()
@@ -213,9 +200,4 @@ EGLSurface getCurrentReadSurface()
     return current->readSurface;
 }
 
-void error(EGLint errorCode)
-{
-    egl::setCurrentError(errorCode);
-}
-
 }
diff --git a/src/3rdparty/angle/src/libEGL/main.h b/src/3rdparty/angle/src/libEGL/main.h
index 07f5b9e6754..e5361a4a5ef 100644
--- a/src/3rdparty/angle/src/libEGL/main.h
+++ b/src/3rdparty/angle/src/libEGL/main.h
@@ -9,6 +9,8 @@
 #ifndef LIBEGL_MAIN_H_
 #define LIBEGL_MAIN_H_
 
+#include "libEGL/Error.h"
+
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
@@ -23,7 +25,7 @@ struct Current
     EGLSurface readSurface;
 };
 
-void setCurrentError(EGLint error);
+void recordError(const Error &error);
 EGLint getCurrentError();
 
 void setCurrentAPI(EGLenum API);
@@ -38,24 +40,6 @@ EGLSurface getCurrentDrawSurface();
 void setCurrentReadSurface(EGLSurface surface);
 EGLSurface getCurrentReadSurface();
 
-void error(EGLint errorCode);
-
-template<class T>
-const T &error(EGLint errorCode, const T &returnValue)
-{
-    error(errorCode);
-
-    return returnValue;
-}
-
-template<class T>
-const T &success(const T &returnValue)
-{
-    egl::setCurrentError(EGL_SUCCESS);
-
-    return returnValue;
-}
-
 }
 
 #endif  // LIBEGL_MAIN_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h
index 4d7dde04e1e..4f7f5f2c85f 100644
--- a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h
+++ b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h
@@ -15,6 +15,7 @@
 #include <cstddef>
 #include <string>
 #include <vector>
+#include <stdint.h>
 
 namespace gl
 {
@@ -26,7 +27,7 @@ class BinaryInputStream
     {
         mError = false;
         mOffset = 0;
-        mData = static_cast<const char*>(data);
+        mData = static_cast<const uint8_t*>(data);
         mLength = length;
     }
 
@@ -85,7 +86,7 @@ class BinaryInputStream
             return;
         }
 
-        v->assign(mData + mOffset, length);
+        v->assign(reinterpret_cast<const char *>(mData) + mOffset, length);
         mOffset += length;
     }
 
@@ -115,11 +116,16 @@ class BinaryInputStream
         return mOffset == mLength;
     }
 
+    const uint8_t *data()
+    {
+        return mData;
+    }
+
   private:
     DISALLOW_COPY_AND_ASSIGN(BinaryInputStream);
     bool mError;
     size_t mOffset;
-    const char *mData;
+    const uint8_t *mData;
     size_t mLength;
 
     template <typename T>
diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h
index 35a6767502c..daa862ca0d5 100644
--- a/src/3rdparty/angle/src/libGLESv2/Buffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h
@@ -19,7 +19,6 @@
 
 namespace rx
 {
-class Renderer;
 class BufferImpl;
 };
 
diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp
index 5342de1331b..b87689cd3f5 100644
--- a/src/3rdparty/angle/src/libGLESv2/Context.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp
@@ -9,10 +9,8 @@
 
 #include "libGLESv2/Context.h"
 
-#include "libGLESv2/main.h"
 #include "common/utilities.h"
 #include "common/platform.h"
-#include "libGLESv2/formatutils.h"
 #include "libGLESv2/Buffer.h"
 #include "libGLESv2/Fence.h"
 #include "libGLESv2/Framebuffer.h"
@@ -21,14 +19,15 @@
 #include "libGLESv2/Program.h"
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/Query.h"
-#include "libGLESv2/Texture.h"
 #include "libGLESv2/ResourceManager.h"
-#include "libGLESv2/renderer/d3d/IndexDataManager.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/VertexArray.h"
 #include "libGLESv2/Sampler.h"
-#include "libGLESv2/validationES.h"
+#include "libGLESv2/Texture.h"
 #include "libGLESv2/TransformFeedback.h"
+#include "libGLESv2/VertexArray.h"
+#include "libGLESv2/formatutils.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/validationES.h"
+#include "libGLESv2/renderer/Renderer.h"
 
 #include "libEGL/Surface.h"
 
@@ -38,7 +37,7 @@
 namespace gl
 {
 
-Context::Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
+Context::Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
     : mRenderer(renderer)
 {
     ASSERT(robustAccess == false);   // Unimplemented
@@ -66,22 +65,24 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere
     // In order that access to these initial textures not be lost, they are treated as texture
     // objects all of whose names are 0.
 
-    mZeroTextures[GL_TEXTURE_2D].set(new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0));
-    bindTexture(GL_TEXTURE_2D, 0);
+    Texture2D *zeroTexture2D = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0);
+    mZeroTextures[GL_TEXTURE_2D].set(zeroTexture2D);
 
-    mZeroTextures[GL_TEXTURE_CUBE_MAP].set(new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0));
-    bindTexture(GL_TEXTURE_CUBE_MAP, 0);
+    TextureCubeMap *zeroTextureCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0);
+    mZeroTextures[GL_TEXTURE_CUBE_MAP].set(zeroTextureCube);
 
     if (mClientVersion >= 3)
     {
         // TODO: These could also be enabled via extension
-        mZeroTextures[GL_TEXTURE_3D].set(new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0));
-        bindTexture(GL_TEXTURE_3D, 0);
+        Texture3D *zeroTexture3D = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0);
+        mZeroTextures[GL_TEXTURE_3D].set(zeroTexture3D);
 
-        mZeroTextures[GL_TEXTURE_2D_ARRAY].set(new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0));
-        bindTexture(GL_TEXTURE_2D_ARRAY, 0);
+        Texture2DArray *zeroTexture2DArray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0);
+        mZeroTextures[GL_TEXTURE_2D_ARRAY].set(zeroTexture2DArray);
     }
 
+    mState.initializeZeroTextures(mZeroTextures);
+
     bindVertexArray(0);
     bindArrayBuffer(0);
     bindElementArrayBuffer(0);
@@ -91,13 +92,13 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere
     bindRenderbuffer(0);
 
     bindGenericUniformBuffer(0);
-    for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++)
+    for (unsigned int i = 0; i < mCaps.maxCombinedUniformBlocks; i++)
     {
         bindIndexedUniformBuffer(0, i, 0, -1);
     }
 
     bindGenericTransformFeedbackBuffer(0);
-    for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
+    for (unsigned int i = 0; i < mCaps.maxTransformFeedbackSeparateAttributes; i++)
     {
         bindIndexedTransformFeedbackBuffer(0, i, 0, -1);
     }
@@ -119,8 +120,6 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere
     mResetStatus = GL_NO_ERROR;
     mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
     mRobustAccess = robustAccess;
-
-    mState.setContext(this);
 }
 
 Context::~Context()
@@ -175,7 +174,10 @@ Context::~Context()
     }
     mZeroTextures.clear();
 
-    mResourceManager->release();
+    if (mResourceManager)
+    {
+        mResourceManager->release();
+    }
 }
 
 void Context::makeCurrent(egl::Surface *surface)
@@ -194,14 +196,11 @@ void Context::makeCurrent(egl::Surface *surface)
     // Wrap the existing swapchain resources into GL objects and assign them to the '0' names
     rx::SwapChain *swapchain = surface->getSwapChain();
 
-    Colorbuffer *colorbufferZero = new Colorbuffer(mRenderer, swapchain);
-    DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(mRenderer, swapchain);
-    Framebuffer *framebufferZero = new DefaultFramebuffer(mRenderer, colorbufferZero, depthStencilbufferZero);
+    rx::RenderbufferImpl *colorbufferZero = mRenderer->createRenderbuffer(swapchain, false);
+    rx::RenderbufferImpl *depthStencilbufferZero = mRenderer->createRenderbuffer(swapchain, true);
+    Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero);
 
     setFramebufferZero(framebufferZero);
-
-    // Store the current client version in the renderer
-    mRenderer->setCurrentClientVersion(mClientVersion);
 }
 
 // NOTE: this function should not assume that this context is current!
@@ -229,7 +228,7 @@ GLuint Context::createProgram()
 
 GLuint Context::createShader(GLenum type)
 {
-    return mResourceManager->createShader(type);
+    return mResourceManager->createShader(getData(), type);
 }
 
 GLuint Context::createTexture()
@@ -242,15 +241,10 @@ GLuint Context::createRenderbuffer()
     return mResourceManager->createRenderbuffer();
 }
 
-GLsync Context::createFenceSync(GLenum condition)
+GLsync Context::createFenceSync()
 {
     GLuint handle = mResourceManager->createFenceSync();
 
-    gl::FenceSync *fenceSync = mResourceManager->getFenceSync(handle);
-    ASSERT(fenceSync);
-
-    fenceSync->set(condition);
-
     return reinterpret_cast<GLsync>(handle);
 }
 
@@ -294,7 +288,7 @@ GLuint Context::createFenceNV()
 {
     GLuint handle = mFenceNVHandleAllocator.allocate();
 
-    mFenceNVMap[handle] = new FenceNV(mRenderer);
+    mFenceNVMap[handle] = new FenceNV(mRenderer->createFenceNV());
 
     return handle;
 }
@@ -355,12 +349,12 @@ void Context::deleteFenceSync(GLsync fenceSync)
     // wait commands finish. However, since the name becomes invalid, we cannot query the fence,
     // and since our API is currently designed for being called from a single thread, we can delete
     // the fence immediately.
-    mResourceManager->deleteFenceSync(uintptr_t(fenceSync));
+    mResourceManager->deleteFenceSync(reinterpret_cast<uintptr_t>(fenceSync));
 }
 
 void Context::deleteVertexArray(GLuint vertexArray)
 {
-    auto vertexArrayObject = mVertexArrayMap.find(vertexArray);
+    VertexArrayMap::iterator vertexArrayObject = mVertexArrayMap.find(vertexArray);
 
     if (vertexArrayObject != mVertexArrayMap.end())
     {
@@ -461,12 +455,12 @@ Renderbuffer *Context::getRenderbuffer(GLuint handle)
 
 FenceSync *Context::getFenceSync(GLsync handle) const
 {
-    return mResourceManager->getFenceSync(uintptr_t(handle));
+    return mResourceManager->getFenceSync(reinterpret_cast<uintptr_t>(handle));
 }
 
 VertexArray *Context::getVertexArray(GLuint handle) const
 {
-    auto vertexArray = mVertexArrayMap.find(handle);
+    VertexArrayMap::const_iterator vertexArray = mVertexArrayMap.find(handle);
 
     if (vertexArray == mVertexArrayMap.end())
     {
@@ -515,18 +509,30 @@ void Context::bindElementArrayBuffer(unsigned int buffer)
     mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer));
 }
 
-void Context::bindTexture(GLenum target, GLuint texture)
+void Context::bindTexture(GLenum target, GLuint handle)
 {
-    mResourceManager->checkTextureAllocation(texture, target);
+    Texture *texture = NULL;
+
+    if (handle == 0)
+    {
+        texture = mZeroTextures[target].get();
+    }
+    else
+    {
+        mResourceManager->checkTextureAllocation(handle, target);
+        texture = getTexture(handle);
+    }
 
-    mState.setSamplerTexture(target, getTexture(texture));
+    ASSERT(texture);
+
+    mState.setSamplerTexture(target, texture);
 }
 
 void Context::bindReadFramebuffer(GLuint framebuffer)
 {
     if (!getFramebuffer(framebuffer))
     {
-        mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer);
+        mFramebufferMap[framebuffer] = new Framebuffer(framebuffer);
     }
 
     mState.setReadFramebufferBinding(getFramebuffer(framebuffer));
@@ -536,7 +542,7 @@ void Context::bindDrawFramebuffer(GLuint framebuffer)
 {
     if (!getFramebuffer(framebuffer))
     {
-        mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer);
+        mFramebufferMap[framebuffer] = new Framebuffer(framebuffer);
     }
 
     mState.setDrawFramebufferBinding(getFramebuffer(framebuffer));
@@ -640,33 +646,44 @@ void Context::useProgram(GLuint program)
     }
 }
 
-void Context::linkProgram(GLuint program)
+Error Context::linkProgram(GLuint program)
 {
     Program *programObject = mResourceManager->getProgram(program);
 
-    bool linked = programObject->link(getCaps());
+    Error error = programObject->link(getData());
+    if (error.isError())
+    {
+        return error;
+    }
 
     // if the current program was relinked successfully we
     // need to install the new executables
-    if (linked && program == mState.getCurrentProgramId())
+    if (programObject->isLinked() && program == mState.getCurrentProgramId())
     {
         mState.setCurrentProgramBinary(programObject->getProgramBinary());
     }
+
+    return Error(GL_NO_ERROR);
 }
 
-void Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length)
+Error Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length)
 {
     Program *programObject = mResourceManager->getProgram(program);
 
-    bool loaded = programObject->setProgramBinary(binaryFormat, binary, length);
+    Error error = programObject->setProgramBinary(binaryFormat, binary, length);
+    if (error.isError())
+    {
+        return error;
+    }
 
     // if the current program was reloaded successfully we
     // need to install the new executables
-    if (loaded && program == mState.getCurrentProgramId())
+    if (programObject->isLinked() && program == mState.getCurrentProgramId())
     {
         mState.setCurrentProgramBinary(programObject->getProgramBinary());
     }
 
+    return Error(GL_NO_ERROR);
 }
 
 void Context::bindTransformFeedback(GLuint transformFeedback)
@@ -724,33 +741,6 @@ void Context::setFramebufferZero(Framebuffer *buffer)
     mFramebufferMap[0] = buffer;
 }
 
-void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
-{
-    ASSERT(getTextureCaps().get(internalformat).renderable);
-
-    RenderbufferStorage *renderbuffer = NULL;
-
-    const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
-    if (formatInfo.depthBits > 0 && formatInfo.stencilBits > 0)
-    {
-        renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples);
-    }
-    else if (formatInfo.depthBits > 0)
-    {
-        renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples);
-    }
-    else if (formatInfo.stencilBits > 0)
-    {
-        renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples);
-    }
-    else
-    {
-        renderbuffer = new gl::Colorbuffer(mRenderer, width, height, internalformat, samples);
-    }
-
-    mState.getCurrentRenderbuffer()->setStorage(renderbuffer);
-}
-
 Framebuffer *Context::getFramebuffer(unsigned int handle) const
 {
     FramebufferMap::const_iterator framebuffer = mFramebufferMap.find(handle);
@@ -837,14 +827,7 @@ Texture2DArray *Context::getTexture2DArray() const
 
 Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const
 {
-    if (mState.getSamplerTextureId(sampler, type) == 0)
-    {
-        return mZeroTextures.at(type).get();
-    }
-    else
-    {
-        return mState.getSamplerTexture(sampler, type);
-    }
+    return mState.getSamplerTexture(sampler, type);
 }
 
 void Context::getBooleanv(GLenum pname, GLboolean *params)
@@ -962,7 +945,7 @@ void Context::getIntegerv(GLenum pname, GLint *params)
         *params = static_cast<GLint>(mExtensionStrings.size());
         break;
       default:
-        mState.getIntegerv(pname, params);
+        mState.getIntegerv(getData(), pname, params);
         break;
     }
 }
@@ -1309,309 +1292,6 @@ bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned
     return false;
 }
 
-// Applies the render target surface, depth stencil surface, viewport rectangle and
-// scissor rectangle to the renderer
-Error Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport)
-{
-    Framebuffer *framebufferObject = mState.getDrawFramebuffer();
-    ASSERT(framebufferObject && framebufferObject->completeness() == GL_FRAMEBUFFER_COMPLETE);
-
-    gl::Error error = mRenderer->applyRenderTarget(framebufferObject);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    float nearZ, farZ;
-    mState.getDepthRange(&nearZ, &farZ);
-    mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace,
-                           ignoreViewport);
-
-    mRenderer->setScissorRectangle(mState.getScissor(), mState.isScissorTestEnabled());
-
-    return gl::Error(GL_NO_ERROR);
-}
-
-// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
-Error Context::applyState(GLenum drawMode)
-{
-    Framebuffer *framebufferObject = mState.getDrawFramebuffer();
-    int samples = framebufferObject->getSamples();
-
-    RasterizerState rasterizer = mState.getRasterizerState();
-    rasterizer.pointDrawMode = (drawMode == GL_POINTS);
-    rasterizer.multiSample = (samples != 0);
-
-    Error error = mRenderer->setRasterizerState(rasterizer);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    unsigned int mask = 0;
-    if (mState.isSampleCoverageEnabled())
-    {
-        GLclampf coverageValue;
-        bool coverageInvert = false;
-        mState.getSampleCoverageParams(&coverageValue, &coverageInvert);
-        if (coverageValue != 0)
-        {
-            float threshold = 0.5f;
-
-            for (int i = 0; i < samples; ++i)
-            {
-                mask <<= 1;
-
-                if ((i + 1) * coverageValue >= threshold)
-                {
-                    threshold += 1.0f;
-                    mask |= 1;
-                }
-            }
-        }
-
-        if (coverageInvert)
-        {
-            mask = ~mask;
-        }
-    }
-    else
-    {
-        mask = 0xFFFFFFFF;
-    }
-    error = mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    error = mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(),
-                                            rasterizer.frontFace == GL_CCW);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    return Error(GL_NO_ERROR);
-}
-
-// Applies the shaders and shader constants to the Direct3D 9 device
-Error Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive)
-{
-    const VertexAttribute *vertexAttributes = mState.getVertexArray()->getVertexAttributes();
-
-    VertexFormat inputLayout[MAX_VERTEX_ATTRIBS];
-    VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.getVertexAttribCurrentValues());
-
-    const Framebuffer *fbo = mState.getDrawFramebuffer();
-
-    Error error = mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    return programBinary->applyUniforms();
-}
-
-Error Context::generateSwizzles(ProgramBinary *programBinary, SamplerType type)
-{
-    size_t samplerRange = programBinary->getUsedSamplerRange(type);
-
-    for (size_t i = 0; i < samplerRange; i++)
-    {
-        GLenum textureType = programBinary->getSamplerTextureType(type, i);
-        GLint textureUnit = programBinary->getSamplerMapping(type, i, getCaps());
-        if (textureUnit != -1)
-        {
-            Texture* texture = getSamplerTexture(textureUnit, textureType);
-            if (texture->getSamplerState().swizzleRequired())
-            {
-                Error error = mRenderer->generateSwizzle(texture);
-                if (error.isError())
-                {
-                    return error;
-                }
-            }
-        }
-    }
-
-    return Error(GL_NO_ERROR);
-}
-
-Error Context::generateSwizzles(ProgramBinary *programBinary)
-{
-    Error error = generateSwizzles(programBinary, SAMPLER_VERTEX);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    error = generateSwizzles(programBinary, SAMPLER_PIXEL);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    return Error(GL_NO_ERROR);
-}
-
-// For each Direct3D sampler of either the pixel or vertex stage,
-// looks up the corresponding OpenGL texture image unit and texture type,
-// and sets the texture and its addressing/filtering state (or NULL when inactive).
-Error Context::applyTextures(ProgramBinary *programBinary, SamplerType shaderType,
-                             const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount)
-{
-    size_t samplerRange = programBinary->getUsedSamplerRange(shaderType);
-    for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
-    {
-        GLenum textureType = programBinary->getSamplerTextureType(shaderType, samplerIndex);
-        GLint textureUnit = programBinary->getSamplerMapping(shaderType, samplerIndex, getCaps());
-        if (textureUnit != -1)
-        {
-            SamplerState sampler;
-            Texture* texture = getSamplerTexture(textureUnit, textureType);
-            texture->getSamplerStateWithNativeOffset(&sampler);
-
-            Sampler *samplerObject = mState.getSampler(textureUnit);
-            if (samplerObject)
-            {
-                samplerObject->getState(&sampler);
-            }
-
-            // TODO: std::binary_search may become unavailable using older versions of GCC
-            if (texture->isSamplerComplete(sampler, mTextureCaps, mExtensions, mClientVersion) &&
-                !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial()))
-            {
-                Error error = mRenderer->setSamplerState(shaderType, samplerIndex, sampler);
-                if (error.isError())
-                {
-                    return error;
-                }
-
-                error = mRenderer->setTexture(shaderType, samplerIndex, texture);
-                if (error.isError())
-                {
-                    return error;
-                }
-            }
-            else
-            {
-                // Texture is not sampler complete or it is in use by the framebuffer.  Bind the incomplete texture.
-                Texture *incompleteTexture = getIncompleteTexture(textureType);
-                gl::Error error = mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture);
-                if (error.isError())
-                {
-                    return error;
-                }
-            }
-        }
-        else
-        {
-            // No texture bound to this slot even though it is used by the shader, bind a NULL texture
-            Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL);
-            if (error.isError())
-            {
-                return error;
-            }
-        }
-    }
-
-    // Set all the remaining textures to NULL
-    size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? mCaps.maxTextureImageUnits
-                                                        : mCaps.maxVertexTextureImageUnits;
-    for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
-    {
-        Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL);
-        if (error.isError())
-        {
-            return error;
-        }
-    }
-
-    return Error(GL_NO_ERROR);
-}
-
-Error Context::applyTextures(ProgramBinary *programBinary)
-{
-    FramebufferTextureSerialArray framebufferSerials;
-    size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&framebufferSerials);
-
-    Error error = applyTextures(programBinary, SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    error = applyTextures(programBinary, SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    return Error(GL_NO_ERROR);
-}
-
-Error Context::applyUniformBuffers()
-{
-    Program *programObject = getProgram(mState.getCurrentProgramId());
-    ProgramBinary *programBinary = programObject->getProgramBinary();
-
-    std::vector<Buffer*> boundBuffers;
-
-    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++)
-    {
-        GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex);
-
-        if (mState.getIndexedUniformBuffer(blockBinding)->id() == 0)
-        {
-            // undefined behaviour
-            return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer.");
-        }
-        else
-        {
-            Buffer *uniformBuffer = mState.getIndexedUniformBuffer(blockBinding);
-            ASSERT(uniformBuffer);
-            boundBuffers.push_back(uniformBuffer);
-        }
-    }
-
-    return programBinary->applyUniformBuffers(boundBuffers, getCaps());
-}
-
-bool Context::applyTransformFeedbackBuffers()
-{
-    TransformFeedback *curTransformFeedback = mState.getCurrentTransformFeedback();
-    if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
-    {
-        Buffer *transformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
-        GLintptr transformFeedbackOffsets[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
-        for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
-        {
-            transformFeedbackBuffers[i] = mState.getIndexedTransformFeedbackBuffer(i);
-            transformFeedbackOffsets[i] = mState.getIndexedTransformFeedbackBufferOffset(i);
-        }
-        mRenderer->applyTransformFeedbackBuffers(transformFeedbackBuffers, transformFeedbackOffsets);
-        return true;
-    }
-    else
-    {
-        return false;
-    }
-}
-
-void Context::markTransformFeedbackUsage()
-{
-    for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
-    {
-        Buffer *buffer = mState.getIndexedTransformFeedbackBuffer(i);
-        if (buffer)
-        {
-            buffer->markTransformFeedbackUsage();
-        }
-    }
-}
-
 Error Context::clear(GLbitfield mask)
 {
     if (mState.isRasterizerDiscardEnabled())
@@ -1619,290 +1299,71 @@ Error Context::clear(GLbitfield mask)
         return Error(GL_NO_ERROR);
     }
 
-    ClearParameters clearParams = mState.getClearParameters(mask);
-
-    applyRenderTarget(GL_TRIANGLES, true);   // Clips the clear to the scissor rectangle but not the viewport
-
-    return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+    return mRenderer->clear(getData(), mask);
 }
 
-Error Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values)
+Error Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values)
 {
     if (mState.isRasterizerDiscardEnabled())
     {
         return Error(GL_NO_ERROR);
     }
 
-    // glClearBufferfv can be called to clear the color buffer or depth buffer
-    ClearParameters clearParams = mState.getClearParameters(0);
-
-    if (buffer == GL_COLOR)
-    {
-        for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
-        {
-            clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
-        }
-        clearParams.colorFClearValue = ColorF(values[0], values[1], values[2], values[3]);
-        clearParams.colorClearType = GL_FLOAT;
-    }
-
-    if (buffer == GL_DEPTH)
-    {
-        clearParams.clearDepth = true;
-        clearParams.depthClearValue = values[0];
-    }
-
-    applyRenderTarget(GL_TRIANGLES, true);   // Clips the clear to the scissor rectangle but not the viewport
-
-    return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+    return mRenderer->clearBufferfv(getData(), buffer, drawbuffer, values);
 }
 
-Error Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values)
+Error Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values)
 {
     if (mState.isRasterizerDiscardEnabled())
     {
         return Error(GL_NO_ERROR);
     }
 
-    // glClearBufferuv can only be called to clear a color buffer
-    ClearParameters clearParams = mState.getClearParameters(0);
-    for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
-    {
-        clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
-    }
-    clearParams.colorUIClearValue = ColorUI(values[0], values[1], values[2], values[3]);
-    clearParams.colorClearType = GL_UNSIGNED_INT;
-
-    applyRenderTarget(GL_TRIANGLES, true);   // Clips the clear to the scissor rectangle but not the viewport
-
-    return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+    return mRenderer->clearBufferuiv(getData(), buffer, drawbuffer, values);
 }
 
-Error Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values)
+Error Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values)
 {
     if (mState.isRasterizerDiscardEnabled())
     {
         return Error(GL_NO_ERROR);
     }
 
-    // glClearBufferfv can be called to clear the color buffer or stencil buffer
-    ClearParameters clearParams = mState.getClearParameters(0);
-
-    if (buffer == GL_COLOR)
-    {
-        for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
-        {
-            clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
-        }
-        clearParams.colorIClearValue = ColorI(values[0], values[1], values[2], values[3]);
-        clearParams.colorClearType = GL_INT;
-    }
-
-    if (buffer == GL_STENCIL)
-    {
-        clearParams.clearStencil = true;
-        clearParams.stencilClearValue = values[1];
-    }
-
-    applyRenderTarget(GL_TRIANGLES, true);   // Clips the clear to the scissor rectangle but not the viewport
-
-    return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+    return mRenderer->clearBufferiv(getData(), buffer, drawbuffer, values);
 }
 
-Error Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil)
+Error Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
 {
     if (mState.isRasterizerDiscardEnabled())
     {
         return Error(GL_NO_ERROR);
     }
 
-    // glClearBufferfi can only be called to clear a depth stencil buffer
-    ClearParameters clearParams = mState.getClearParameters(0);
-    clearParams.clearDepth = true;
-    clearParams.depthClearValue = depth;
-    clearParams.clearStencil = true;
-    clearParams.stencilClearValue = stencil;
-
-    applyRenderTarget(GL_TRIANGLES, true);   // Clips the clear to the scissor rectangle but not the viewport
-
-    return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+    return mRenderer->clearBufferfi(getData(), buffer, drawbuffer, depth, stencil);
 }
 
 Error Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
                           GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
 {
-    Framebuffer *framebuffer = mState.getReadFramebuffer();
-
-    GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
-    const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat);
-    GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, mState.getPackAlignment());
-
-    return mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(),
-                                 reinterpret_cast<uint8_t*>(pixels));
+    return mRenderer->readPixels(getData(), x, y, width, height, format, type, bufSize, pixels);
 }
 
 Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
 {
-    ASSERT(mState.getCurrentProgramId() != 0);
-
-    ProgramBinary *programBinary = mState.getCurrentProgramBinary();
-    programBinary->updateSamplerMapping();
-
-    Error error = generateSwizzles(programBinary);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    if (!mRenderer->applyPrimitiveType(mode, count))
-    {
-        return Error(GL_NO_ERROR);
-    }
-
-    error = applyRenderTarget(mode, false);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    error = applyState(mode);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    error = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    bool transformFeedbackActive = applyTransformFeedbackBuffers();
-
-    error = applyShaders(programBinary, transformFeedbackActive);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    error = applyTextures(programBinary);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    error = applyUniformBuffers();
-    if (error.isError())
-    {
-        return error;
-    }
-
-    if (!skipDraw(mode))
-    {
-        error = mRenderer->drawArrays(mode, count, instances, transformFeedbackActive);
-        if (error.isError())
-        {
-            return error;
-        }
-
-        if (transformFeedbackActive)
-        {
-            markTransformFeedbackUsage();
-        }
-    }
-
-    return gl::Error(GL_NO_ERROR);
+    return mRenderer->drawArrays(getData(), mode, first, count, instances);
 }
 
 Error Context::drawElements(GLenum mode, GLsizei count, GLenum type,
                             const GLvoid *indices, GLsizei instances,
                             const rx::RangeUI &indexRange)
 {
-    ASSERT(mState.getCurrentProgramId() != 0);
-
-    ProgramBinary *programBinary = mState.getCurrentProgramBinary();
-    programBinary->updateSamplerMapping();
-
-    Error error = generateSwizzles(programBinary);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    if (!mRenderer->applyPrimitiveType(mode, count))
-    {
-        return Error(GL_NO_ERROR);
-    }
-
-    error = applyRenderTarget(mode, false);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    error = applyState(mode);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    VertexArray *vao = mState.getVertexArray();
-    rx::TranslatedIndexData indexInfo;
-    indexInfo.indexRange = indexRange;
-    error = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    GLsizei vertexCount = indexInfo.indexRange.length() + 1;
-    error = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(),
-                                         mState.getVertexAttribCurrentValues(),
-                                         indexInfo.indexRange.start, vertexCount, instances);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    bool transformFeedbackActive = applyTransformFeedbackBuffers();
-    // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation
-    // layer.
-    ASSERT(!transformFeedbackActive);
-
-    error = applyShaders(programBinary, transformFeedbackActive);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    error = applyTextures(programBinary);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    error = applyUniformBuffers();
-    if (error.isError())
-    {
-        return error;
-    }
-
-    if (!skipDraw(mode))
-    {
-        error = mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances);
-        if (error.isError())
-        {
-            return error;
-        }
-    }
-
-    return Error(GL_NO_ERROR);
+    return mRenderer->drawElements(getData(), mode, count, type, indices, instances, indexRange);
 }
 
 // Implements glFlush when block is false, glFinish when block is true
-void Context::sync(bool block)
+Error Context::sync(bool block)
 {
-    mRenderer->sync(block);
+    return mRenderer->sync(block);
 }
 
 void Context::recordError(const Error &error)
@@ -1931,6 +1392,7 @@ GLenum Context::getError()
 
 GLenum Context::getResetStatus()
 {
+    //TODO(jmadill): needs MANGLE reworking
     if (mResetStatus == GL_NO_ERROR && !mContextLost)
     {
         // mResetStatus will be set by the markContextLost callback
@@ -1981,7 +1443,7 @@ const Extensions &Context::getExtensions() const
 void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type)
 {
     Framebuffer *framebuffer = mState.getReadFramebuffer();
-    ASSERT(framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE);
+    ASSERT(framebuffer && framebuffer->completeness(getData()) == GL_FRAMEBUFFER_COMPLETE);
 
     FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
     ASSERT(attachment);
@@ -2000,7 +1462,7 @@ void Context::detachTexture(GLuint texture)
     // allocation map management either here or in the resource manager at detach time.
     // Zero textures are held by the Context, and we don't attempt to request them from
     // the State.
-    mState.detachTexture(texture);
+    mState.detachTexture(mZeroTextures, texture);
 }
 
 void Context::detachBuffer(GLuint buffer)
@@ -2072,95 +1534,6 @@ void Context::detachSampler(GLuint sampler)
     mState.detachSampler(sampler);
 }
 
-Texture *Context::getIncompleteTexture(GLenum type)
-{
-    if (mIncompleteTextures.find(type) == mIncompleteTextures.end())
-    {
-        const GLubyte color[] = { 0, 0, 0, 255 };
-        const PixelUnpackState incompleteUnpackState(1);
-
-        Texture* t = NULL;
-        switch (type)
-        {
-          default:
-            UNREACHABLE();
-            // default falls through to TEXTURE_2D
-
-          case GL_TEXTURE_2D:
-            {
-                Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), Texture::INCOMPLETE_TEXTURE_ID);
-                incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-                t = incomplete2d;
-            }
-            break;
-
-          case GL_TEXTURE_CUBE_MAP:
-            {
-              TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), Texture::INCOMPLETE_TEXTURE_ID);
-
-              incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-              incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-              incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-              incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-              incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-              incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-
-              t = incompleteCube;
-            }
-            break;
-
-          case GL_TEXTURE_3D:
-            {
-                Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), Texture::INCOMPLETE_TEXTURE_ID);
-                incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-
-                t = incomplete3d;
-            }
-            break;
-
-          case GL_TEXTURE_2D_ARRAY:
-            {
-                Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), Texture::INCOMPLETE_TEXTURE_ID);
-                incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-
-                t = incomplete2darray;
-            }
-            break;
-        }
-
-        mIncompleteTextures[type].set(t);
-    }
-
-    return mIncompleteTextures[type].get();
-}
-
-bool Context::skipDraw(GLenum drawMode)
-{
-    if (drawMode == GL_POINTS)
-    {
-        // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
-        // which affects varying interpolation. Since the value of gl_PointSize is
-        // undefined when not written, just skip drawing to avoid unexpected results.
-        if (!mState.getCurrentProgramBinary()->usesPointSize())
-        {
-            // This is stictly speaking not an error, but developers should be
-            // notified of risking undefined behavior.
-            ERR("Point rendering without writing to gl_PointSize.");
-
-            return true;
-        }
-    }
-    else if (IsTriangleMode(drawMode))
-    {
-        if (mState.getRasterizerState().cullFace && mState.getRasterizerState().cullMode == GL_FRONT_AND_BACK)
-        {
-            return true;
-        }
-    }
-
-    return false;
-}
-
 void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
 {
     mState.getVertexArray()->setVertexAttribDivisor(index, divisor);
@@ -2293,63 +1666,12 @@ size_t Context::getExtensionStringCount() const
     return mExtensionStrings.size();
 }
 
-size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray)
+Error Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                               GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                               GLbitfield mask, GLenum filter)
 {
-    size_t serialCount = 0;
-
-    Framebuffer *drawFramebuffer = mState.getDrawFramebuffer();
-    for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
-    {
-        FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i);
-        if (attachment && attachment->isTexture())
-        {
-            Texture *texture = attachment->getTexture();
-            (*outSerialArray)[serialCount++] = texture->getTextureSerial();
-        }
-    }
-
-    FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer();
-    if (depthStencilAttachment && depthStencilAttachment->isTexture())
-    {
-        Texture *depthStencilTexture = depthStencilAttachment->getTexture();
-        (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial();
-    }
-
-    std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount);
-
-    return serialCount;
-}
-
-void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                              GLbitfield mask, GLenum filter)
-{
-    Framebuffer *readFramebuffer = mState.getReadFramebuffer();
-    Framebuffer *drawFramebuffer = mState.getDrawFramebuffer();
-
-    bool blitRenderTarget = false;
-    bool blitDepth = false;
-    bool blitStencil = false;
-    if ((mask & GL_COLOR_BUFFER_BIT) && readFramebuffer->getReadColorbuffer() && drawFramebuffer->getFirstColorbuffer())
-    {
-        blitRenderTarget = true;
-    }
-    if ((mask & GL_STENCIL_BUFFER_BIT) && readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
-    {
-        blitStencil = true;
-    }
-    if ((mask & GL_DEPTH_BUFFER_BIT) && readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
-    {
-        blitDepth = true;
-    }
-
-    Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
-    Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
-    if (blitRenderTarget || blitDepth || blitStencil)
-    {
-        const Rectangle *scissor = mState.isScissorTestEnabled() ? &mState.getScissor() : NULL;
-        mRenderer->blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor,
-                            blitRenderTarget, blitDepth, blitStencil, filter);
-    }
+    return mRenderer->blitFramebuffer(getData(), srcX0, srcY0, srcX1, srcY1,
+                                      dstX0, dstY0, dstX1, dstY1, mask, filter);
 }
 
 void Context::releaseShaderCompiler()
@@ -2416,6 +1738,11 @@ void Context::initCaps(GLuint clientVersion)
     mExtensions.maxSamples = maxSamples;
 }
 
+Data Context::getData() const
+{
+    return Data(mClientVersion, mState, mCaps, mTextureCaps, mExtensions, mResourceManager);
+}
+
 }
 
 extern "C"
diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h
index 1b888aec83a..1e890de3ef2 100644
--- a/src/3rdparty/angle/src/libGLESv2/Context.h
+++ b/src/3rdparty/angle/src/libGLESv2/Context.h
@@ -13,12 +13,12 @@
 #include "common/angleutils.h"
 #include "common/RefCountObject.h"
 #include "libGLESv2/Caps.h"
+#include "libGLESv2/Constants.h"
+#include "libGLESv2/Data.h"
 #include "libGLESv2/Error.h"
 #include "libGLESv2/HandleAllocator.h"
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/Constants.h"
 #include "libGLESv2/VertexAttribute.h"
-#include "libGLESv2/State.h"
+#include "libGLESv2/angletypes.h"
 
 #include "angle_gl.h"
 
@@ -50,11 +50,6 @@ class Texture3D;
 class Texture2DArray;
 class Framebuffer;
 class Renderbuffer;
-class RenderbufferStorage;
-class Colorbuffer;
-class Depthbuffer;
-class Stencilbuffer;
-class DepthStencilbuffer;
 class FenceNV;
 class FenceSync;
 class Query;
@@ -68,7 +63,7 @@ class TransformFeedback;
 class Context
 {
   public:
-    Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
+    Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
 
     virtual ~Context();
 
@@ -86,7 +81,7 @@ class Context
     GLuint createRenderbuffer();
     GLuint createSampler();
     GLuint createTransformFeedback();
-    GLsync createFenceSync(GLenum condition);
+    GLsync createFenceSync();
 
     void deleteBuffer(GLuint buffer);
     void deleteShader(GLuint shader);
@@ -115,7 +110,7 @@ class Context
 
     void bindArrayBuffer(GLuint buffer);
     void bindElementArrayBuffer(GLuint buffer);
-    void bindTexture(GLenum target, GLuint texture);
+    void bindTexture(GLenum target, GLuint handle);
     void bindReadFramebuffer(GLuint framebuffer);
     void bindDrawFramebuffer(GLuint framebuffer);
     void bindRenderbuffer(GLuint renderbuffer);
@@ -130,8 +125,8 @@ class Context
     void bindPixelPackBuffer(GLuint buffer);
     void bindPixelUnpackBuffer(GLuint buffer);
     void useProgram(GLuint program);
-    void linkProgram(GLuint program);
-    void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
+    Error linkProgram(GLuint program);
+    Error setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
     void bindTransformFeedback(GLuint transformFeedback);
 
     Error beginQuery(GLenum target, GLuint query);
@@ -139,8 +134,6 @@ class Context
 
     void setFramebufferZero(Framebuffer *framebuffer);
 
-    void setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
-
     void setVertexAttribDivisor(GLuint index, GLuint divisor);
 
     void samplerParameteri(GLuint sampler, GLenum pname, GLint param);
@@ -183,17 +176,17 @@ class Context
     bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams);
 
     Error clear(GLbitfield mask);
-    Error clearBufferfv(GLenum buffer, int drawbuffer, const float *values);
-    Error clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values);
-    Error clearBufferiv(GLenum buffer, int drawbuffer, const int *values);
-    Error clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil);
+    Error clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values);
+    Error clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values);
+    Error clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values);
+    Error clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
 
     Error readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
     Error drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
     Error drawElements(GLenum mode, GLsizei count, GLenum type,
                        const GLvoid *indices, GLsizei instances,
                        const rx::RangeUI &indexRange);
-    void sync(bool block);   // flush/finish
+    Error sync(bool block);   // flush/finish
 
     void recordError(const Error &error);
 
@@ -215,32 +208,21 @@ class Context
 
     void getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type);
 
-    void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                         GLbitfield mask, GLenum filter);
+    Error blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                          GLbitfield mask, GLenum filter);
 
     rx::Renderer *getRenderer() { return mRenderer; }
 
     State &getState() { return mState; }
     const State &getState() const { return mState; }
 
+    Data getData() const;
+
     void releaseShaderCompiler();
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Context);
 
-    // TODO: std::array may become unavailable using older versions of GCC
-    typedef std::array<unsigned int, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureSerialArray;
-
-    Error applyRenderTarget(GLenum drawMode, bool ignoreViewport);
-    Error applyState(GLenum drawMode);
-    Error applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive);
-    Error applyTextures(ProgramBinary *programBinary, SamplerType shaderType, const FramebufferTextureSerialArray &framebufferSerials,
-                        size_t framebufferSerialCount);
-    Error applyTextures(ProgramBinary *programBinary);
-    Error applyUniformBuffers();
-    bool applyTransformFeedbackBuffers();
-    void markTransformFeedbackUsage();
-
     void detachBuffer(GLuint buffer);
     void detachTexture(GLuint texture);
     void detachFramebuffer(GLuint framebuffer);
@@ -249,18 +231,9 @@ class Context
     void detachTransformFeedback(GLuint transformFeedback);
     void detachSampler(GLuint sampler);
 
-    Error generateSwizzles(ProgramBinary *programBinary, SamplerType type);
-    Error generateSwizzles(ProgramBinary *programBinary);
-
-    Texture *getIncompleteTexture(GLenum type);
-
-    bool skipDraw(GLenum drawMode);
-
     void initRendererString();
     void initExtensionStrings();
 
-    size_t getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray);
-
     void initCaps(GLuint clientVersion);
 
     // Caps to use for validation
@@ -273,7 +246,6 @@ class Context
 
     int mClientVersion;
 
-    typedef std::map< GLenum, BindingPointer<Texture> > TextureMap;
     TextureMap mZeroTextures;
     TextureMap mIncompleteTextures;
 
diff --git a/src/3rdparty/angle/src/libGLESv2/Data.cpp b/src/3rdparty/angle/src/libGLESv2/Data.cpp
new file mode 100644
index 00000000000..3ddf591d778
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/Data.cpp
@@ -0,0 +1,51 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Data.cpp: Container class for all GL relevant state, caps and objects
+
+#include "libGLESv2/Data.h"
+#include "libGLESv2/ResourceManager.h"
+
+namespace gl
+{
+
+Data::Data(GLint clientVersionIn, const State &stateIn, const Caps &capsIn,
+           const TextureCapsMap &textureCapsIn, const Extensions &extensionsIn,
+           const ResourceManager *resourceManagerIn)
+    : clientVersion(clientVersionIn),
+      state(&stateIn),
+      caps(&capsIn),
+      textureCaps(&textureCapsIn),
+      extensions(&extensionsIn),
+      resourceManager(resourceManagerIn)
+{}
+
+Data::~Data()
+{
+}
+
+Data::Data(const Data &other)
+    : clientVersion(other.clientVersion),
+      state(other.state),
+      caps(other.caps),
+      textureCaps(other.textureCaps),
+      extensions(other.extensions),
+      resourceManager(other.resourceManager)
+{
+}
+
+Data &Data::operator=(const Data &other)
+{
+    clientVersion = other.clientVersion;
+    state = other.state;
+    caps = other.caps;
+    textureCaps = other.textureCaps;
+    extensions = other.extensions;
+    resourceManager = other.resourceManager;
+    return *this;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Data.h b/src/3rdparty/angle/src/libGLESv2/Data.h
new file mode 100644
index 00000000000..9234403e13f
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/Data.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Data.h: Container class for all GL relevant state, caps and objects
+
+#ifndef LIBGLESV2_DATA_H_
+#define LIBGLESV2_DATA_H_
+
+#include "libGLESv2/State.h"
+
+namespace gl
+{
+
+struct Data
+{
+  public:
+    Data(GLint clientVersion, const State &state, const Caps &caps,
+         const TextureCapsMap &textureCaps, const Extensions &extensions,
+         const ResourceManager *resourceManager);
+    ~Data();
+
+    Data(const Data &other);
+    Data &operator=(const Data &other);
+
+    GLint clientVersion;
+    const State *state;
+    const Caps *caps;
+    const TextureCapsMap *textureCaps;
+    const Extensions *extensions;
+    const ResourceManager *resourceManager;
+};
+
+}
+
+#endif // LIBGLESV2_DATA_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.cpp b/src/3rdparty/angle/src/libGLESv2/Fence.cpp
index ee9a07a5c48..966a327de56 100644
--- a/src/3rdparty/angle/src/libGLESv2/Fence.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Fence.cpp
@@ -4,191 +4,113 @@
 // found in the LICENSE file.
 //
 
-// Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension.
-
-// Important note on accurate timers in Windows:
-//
-// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call
-// as timeGetTime on laptops and "jumping" during certain hardware events.
-//
-// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc"
-//   https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc
-//
-// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer
-// from buggy implementations.
+// Fence.cpp: Implements the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence
+// extension and GLES3 sync objects.
 
 #include "libGLESv2/Fence.h"
 #include "libGLESv2/renderer/FenceImpl.h"
 #include "libGLESv2/renderer/Renderer.h"
 #include "libGLESv2/main.h"
+#include "common/utilities.h"
 
 #include "angle_gl.h"
 
 namespace gl
 {
 
-FenceNV::FenceNV(rx::Renderer *renderer)
+FenceNV::FenceNV(rx::FenceNVImpl *impl)
+    : mFence(impl),
+      mIsSet(false),
+      mStatus(GL_FALSE),
+      mCondition(GL_NONE)
 {
-    mFence = renderer->createFence();
 }
 
 FenceNV::~FenceNV()
 {
-    delete mFence;
+    SafeDelete(mFence);
 }
 
 GLboolean FenceNV::isFence() const
 {
     // GL_NV_fence spec:
     // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
-    return (mFence->isSet() ? GL_TRUE : GL_FALSE);
+    return (mIsSet ? GL_TRUE : GL_FALSE);
 }
 
-void FenceNV::setFence(GLenum condition)
+Error FenceNV::setFence(GLenum condition)
 {
-    mFence->set();
+    Error error = mFence->set();
+    if (error.isError())
+    {
+        return error;
+    }
 
     mCondition = condition;
     mStatus = GL_FALSE;
-}
-
-GLboolean FenceNV::testFence()
-{
-    // Flush the command buffer by default
-    bool result = mFence->test(true);
+    mIsSet = true;
 
-    mStatus = (result ? GL_TRUE : GL_FALSE);
-    return mStatus;
+    return Error(GL_NO_ERROR);
 }
 
-void FenceNV::finishFence()
+Error FenceNV::testFence(GLboolean *outResult)
 {
-    ASSERT(mFence->isSet());
-
-    while (!mFence->test(true))
+    // Flush the command buffer by default
+    Error error = mFence->test(true, &mStatus);
+    if (error.isError())
     {
-        Sleep(0);
+        return error;
     }
-}
-
-GLint FenceNV::getFencei(GLenum pname)
-{
-    ASSERT(mFence->isSet());
 
-    switch (pname)
-    {
-      case GL_FENCE_STATUS_NV:
-        {
-            // GL_NV_fence spec:
-            // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
-            // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
-            if (mStatus == GL_TRUE)
-            {
-                return GL_TRUE;
-            }
-
-            mStatus = (mFence->test(false) ? GL_TRUE : GL_FALSE);
-            return mStatus;
-        }
-
-      case GL_FENCE_CONDITION_NV:
-        return mCondition;
-
-      default: UNREACHABLE(); return 0;
-    }
+    *outResult = mStatus;
+    return Error(GL_NO_ERROR);
 }
 
-FenceSync::FenceSync(rx::Renderer *renderer, GLuint id)
-    : RefCountObject(id)
+Error FenceNV::finishFence()
 {
-    mFence = renderer->createFence();
-
-    LARGE_INTEGER counterFreqency = { 0 };
-    BOOL success = QueryPerformanceFrequency(&counterFreqency);
-    UNUSED_ASSERTION_VARIABLE(success);
-    ASSERT(success);
+    ASSERT(mIsSet);
 
-    mCounterFrequency = counterFreqency.QuadPart;
+    return mFence->finishFence(&mStatus);
 }
 
-FenceSync::~FenceSync()
+FenceSync::FenceSync(rx::FenceSyncImpl *impl, GLuint id)
+    : RefCountObject(id),
+      mFence(impl),
+      mCondition(GL_NONE)
 {
-    delete mFence;
 }
 
-void FenceSync::set(GLenum condition)
+FenceSync::~FenceSync()
 {
-    mCondition = condition;
-    mFence->set();
+    SafeDelete(mFence);
 }
 
-GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout)
+Error FenceSync::set(GLenum condition)
 {
-    ASSERT(mFence->isSet());
-
-    bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0);
-
-    if (mFence->test(flushCommandBuffer))
+    Error error = mFence->set();
+    if (error.isError())
     {
-        return GL_ALREADY_SIGNALED;
+        return error;
     }
 
-    if (mFence->hasError())
-    {
-        return GL_WAIT_FAILED;
-    }
-
-    if (timeout == 0)
-    {
-        return GL_TIMEOUT_EXPIRED;
-    }
-
-    LARGE_INTEGER currentCounter = { 0 };
-    BOOL success = QueryPerformanceCounter(&currentCounter);
-    UNUSED_ASSERTION_VARIABLE(success);
-    ASSERT(success);
-
-    LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll);
-    LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;
-
-    while (currentCounter.QuadPart < endCounter && !mFence->test(flushCommandBuffer))
-    {
-        Sleep(0);
-        BOOL success = QueryPerformanceCounter(&currentCounter);
-        UNUSED_ASSERTION_VARIABLE(success);
-        ASSERT(success);
-    }
-
-    if (mFence->hasError())
-    {
-        return GL_WAIT_FAILED;
-    }
-
-    if (currentCounter.QuadPart >= endCounter)
-    {
-        return GL_TIMEOUT_EXPIRED;
-    }
-
-    return GL_CONDITION_SATISFIED;
+    mCondition = condition;
+    return Error(GL_NO_ERROR);
 }
 
-void FenceSync::serverWait()
+Error FenceSync::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
 {
-    // Because our API is currently designed to be called from a single thread, we don't need to do
-    // extra work for a server-side fence. GPU commands issued after the fence is created will always
-    // be processed after the fence is signaled.
+    ASSERT(mCondition != GL_NONE);
+    return mFence->clientWait(flags, timeout, outResult);
 }
 
-GLenum FenceSync::getStatus() const
+Error FenceSync::serverWait(GLbitfield flags, GLuint64 timeout)
 {
-    if (mFence->test(false))
-    {
-        // The spec does not specify any way to report errors during the status test (e.g. device lost)
-        // so we report the fence is unblocked in case of error or signaled.
-        return GL_SIGNALED;
-    }
+    return mFence->serverWait(flags, timeout);
+}
 
-    return GL_UNSIGNALED;
+Error FenceSync::getStatus(GLint *outResult) const
+{
+    return mFence->getStatus(outResult);
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.h b/src/3rdparty/angle/src/libGLESv2/Fence.h
index 291edb3de12..fd565e96a68 100644
--- a/src/3rdparty/angle/src/libGLESv2/Fence.h
+++ b/src/3rdparty/angle/src/libGLESv2/Fence.h
@@ -4,18 +4,21 @@
 // found in the LICENSE file.
 //
 
-// Fence.h: Defines the gl::Fence class, which supports the GL_NV_fence extension.
+// Fence.h: Defines the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence
+// extension and GLES3 sync objects.
 
 #ifndef LIBGLESV2_FENCE_H_
 #define LIBGLESV2_FENCE_H_
 
+#include "libGLESv2/Error.h"
+
 #include "common/angleutils.h"
 #include "common/RefCountObject.h"
 
 namespace rx
 {
-class Renderer;
-class FenceImpl;
+class FenceNVImpl;
+class FenceSyncImpl;
 }
 
 namespace gl
@@ -24,14 +27,13 @@ namespace gl
 class FenceNV
 {
   public:
-    explicit FenceNV(rx::Renderer *renderer);
+    explicit FenceNV(rx::FenceNVImpl *impl);
     virtual ~FenceNV();
 
     GLboolean isFence() const;
-    void setFence(GLenum condition);
-    GLboolean testFence();
-    void finishFence();
-    GLint getFencei(GLenum pname);
+    Error setFence(GLenum condition);
+    Error testFence(GLboolean *outResult);
+    Error finishFence();
 
     GLboolean getStatus() const { return mStatus; }
     GLuint getCondition() const { return mCondition; }
@@ -39,7 +41,9 @@ class FenceNV
   private:
     DISALLOW_COPY_AND_ASSIGN(FenceNV);
 
-    rx::FenceImpl *mFence;
+    rx::FenceNVImpl *mFence;
+
+    bool mIsSet;
 
     GLboolean mStatus;
     GLenum mCondition;
@@ -48,21 +52,20 @@ class FenceNV
 class FenceSync : public RefCountObject
 {
   public:
-    explicit FenceSync(rx::Renderer *renderer, GLuint id);
+    explicit FenceSync(rx::FenceSyncImpl *impl, GLuint id);
     virtual ~FenceSync();
 
-    void set(GLenum condition);
-    GLenum clientWait(GLbitfield flags, GLuint64 timeout);
-    void serverWait();
-    GLenum getStatus() const;
+    Error set(GLenum condition);
+    Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult);
+    Error serverWait(GLbitfield flags, GLuint64 timeout);
+    Error getStatus(GLint *outResult) const;
 
     GLuint getCondition() const { return mCondition; }
 
   private:
     DISALLOW_COPY_AND_ASSIGN(FenceSync);
 
-    rx::FenceImpl *mFence;
-    LONGLONG mCounterFrequency;
+    rx::FenceSyncImpl *mFence;
 
     GLenum mCondition;
 };
diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
index 5b21433f905..3d57262e3c3 100644
--- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
@@ -16,13 +16,18 @@
 #include "libGLESv2/FramebufferAttachment.h"
 #include "libGLESv2/renderer/Renderer.h"
 #include "libGLESv2/renderer/RenderTarget.h"
+#include "libGLESv2/renderer/RenderbufferImpl.h"
+#include "libGLESv2/renderer/Workarounds.h"
 #include "libGLESv2/renderer/d3d/TextureD3D.h"
+#include "libGLESv2/renderer/d3d/RenderbufferD3D.h"
 
 #include "common/utilities.h"
 
 namespace rx
 {
-RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
+// TODO: Move these functions, and the D3D-specific header inclusions above,
+//       to FramebufferD3D.
+gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT)
 {
     if (attachment->isTexture())
     {
@@ -31,14 +36,16 @@ RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
         TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
         const gl::ImageIndex *index = attachment->getTextureImageIndex();
         ASSERT(index);
-        return textureD3D->getRenderTarget(*index);
+        return textureD3D->getRenderTarget(*index, outRT);
+    }
+    else
+    {
+        gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
+        ASSERT(renderbuffer);
+        RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
+        *outRT = renderbufferD3D->getRenderTarget();
+        return gl::Error(GL_NO_ERROR);
     }
-
-    gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
-    ASSERT(renderbuffer);
-
-    // TODO: cast to RenderbufferD3D
-    return renderbuffer->getStorage()->getRenderTarget();
 }
 
 // Note: RenderTarget serials should ideally be in the RenderTargets themselves.
@@ -56,9 +63,8 @@ unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
 
     gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
     ASSERT(renderbuffer);
-
-    // TODO: cast to RenderbufferD3D
-    return renderbuffer->getStorage()->getSerial();
+    RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
+    return renderbufferD3D->getRenderTargetSerial();
 }
 
 }
@@ -66,9 +72,8 @@ unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
 namespace gl
 {
 
-Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id)
-    : mRenderer(renderer),
-      mId(id),
+Framebuffer::Framebuffer(GLuint id)
+    : mId(id),
       mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
       mDepthbuffer(NULL),
       mStencilbuffer(NULL)
@@ -91,124 +96,6 @@ Framebuffer::~Framebuffer()
     SafeDelete(mStencilbuffer);
 }
 
-FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const
-{
-    if (handle == 0)
-    {
-        return NULL;
-    }
-
-    gl::Context *context = gl::getContext();
-
-    switch (type)
-    {
-      case GL_NONE:
-        return NULL;
-
-      case GL_RENDERBUFFER:
-        return new RenderbufferAttachment(binding, context->getRenderbuffer(handle));
-
-      case GL_TEXTURE_2D:
-        {
-            Texture *texture = context->getTexture(handle);
-            if (texture && texture->getTarget() == GL_TEXTURE_2D)
-            {
-                return new TextureAttachment(binding, texture, ImageIndex::Make2D(level));
-            }
-            else
-            {
-                return NULL;
-            }
-        }
-
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-        {
-            Texture *texture = context->getTexture(handle);
-            if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
-            {
-                return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level));
-            }
-            else
-            {
-                return NULL;
-            }
-        }
-
-      case GL_TEXTURE_3D:
-        {
-            Texture *texture = context->getTexture(handle);
-            if (texture && texture->getTarget() == GL_TEXTURE_3D)
-            {
-                return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer));
-            }
-            else
-            {
-                return NULL;
-            }
-        }
-
-      case GL_TEXTURE_2D_ARRAY:
-        {
-            Texture *texture = context->getTexture(handle);
-            if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
-            {
-                return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer));
-            }
-            else
-            {
-                return NULL;
-            }
-        }
-
-      default:
-        UNREACHABLE();
-        return NULL;
-    }
-}
-
-void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
-{
-    ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
-    SafeDelete(mColorbuffers[colorAttachment]);
-    GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0;
-    mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer);
-}
-
-void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
-{
-    SafeDelete(mDepthbuffer);
-    mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer);
-}
-
-void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
-{
-    SafeDelete(mStencilbuffer);
-    mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer);
-}
-
-void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
-{
-    FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
-
-    SafeDelete(mDepthbuffer);
-    SafeDelete(mStencilbuffer);
-
-    // ensure this is a legitimate depth+stencil format
-    if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
-    {
-        mDepthbuffer = attachment;
-
-        // Make a new attachment object to ensure we do not double-delete
-        // See angle issue 686
-        mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
-    }
-}
-
 void Framebuffer::detachTexture(GLuint textureId)
 {
     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
@@ -382,14 +269,13 @@ bool Framebuffer::usingExtendedDrawBuffers() const
     return false;
 }
 
-GLenum Framebuffer::completeness() const
+GLenum Framebuffer::completeness(const gl::Data &data) const
 {
     int width = 0;
     int height = 0;
     unsigned int colorbufferSize = 0;
     int samples = -1;
     bool missingAttachment = true;
-    GLuint clientVersion = mRenderer->getCurrentClientVersion();
 
     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
     {
@@ -403,8 +289,7 @@ GLenum Framebuffer::completeness() const
             }
 
             GLenum internalformat = colorbuffer->getInternalFormat();
-            // TODO(geofflang): use context's texture caps
-            const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
+            const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
             const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
             if (colorbuffer->isTexture())
             {
@@ -443,7 +328,7 @@ GLenum Framebuffer::completeness() const
 
                 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
                 // in GLES 3.0, there is no such restriction
-                if (clientVersion < 3)
+                if (data.clientVersion < 3)
                 {
                     if (formatInfo.pixelBytes != colorbufferSize)
                     {
@@ -483,14 +368,12 @@ GLenum Framebuffer::completeness() const
         }
 
         GLenum internalformat = mDepthbuffer->getInternalFormat();
-        // TODO(geofflang): use context's texture caps
-        const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
+        const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
         const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
         if (mDepthbuffer->isTexture())
         {
             // depth texture attachments require OES/ANGLE_depth_texture
-            // TODO(geofflang): use context's extensions
-            if (!mRenderer->getRendererExtensions().depthTextures)
+            if (!data.extensions->depthTextures)
             {
                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
             }
@@ -538,15 +421,13 @@ GLenum Framebuffer::completeness() const
         }
 
         GLenum internalformat = mStencilbuffer->getInternalFormat();
-        // TODO(geofflang): use context's texture caps
-        const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
+        const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
         const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
         if (mStencilbuffer->isTexture())
         {
             // texture stencil attachments come along as part
             // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
-            // TODO(geofflang): use context's extensions
-            if (!mRenderer->getRendererExtensions().depthTextures)
+            if (!data.extensions->depthTextures)
             {
                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
             }
@@ -602,42 +483,44 @@ GLenum Framebuffer::completeness() const
     return GL_FRAMEBUFFER_COMPLETE;
 }
 
-void Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
+Error Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
 {
     GLuint maxDimension = caps.maxRenderbufferSize;
-    invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension);
+    return invalidateSub(numAttachments, attachments, 0, 0, maxDimension, maxDimension);
 }
 
-void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments,
-                                GLint x, GLint y, GLsizei width, GLsizei height)
+Error Framebuffer::invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height)
 {
-    ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE);
     for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex)
     {
         GLenum attachmentTarget = attachments[attachIndex];
 
-        gl::FramebufferAttachment *attachment =
-            (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() :
-                                                                getAttachment(attachmentTarget);
+        FramebufferAttachment *attachment = (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer()
+                                                                                              : getAttachment(attachmentTarget);
 
         if (attachment)
         {
-            rx::RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
-            if (renderTarget)
+            rx::RenderTarget *renderTarget = NULL;
+            Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget);
+            if (error.isError())
             {
-                renderTarget->invalidate(x, y, width, height);
+                return error;
             }
+
+            renderTarget->invalidate(x, y, width, height);
         }
     }
+
+    return Error(GL_NO_ERROR);
 }
 
-DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
-    : Framebuffer(renderer, 0)
+DefaultFramebuffer::DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil)
+    : Framebuffer(0)
 {
-    Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer);
+    Renderbuffer *colorRenderbuffer = new Renderbuffer(colorbuffer, 0);
     mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer);
 
-    Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil);
+    Renderbuffer *depthStencilBuffer = new Renderbuffer(depthStencil, 0);
 
     // Make a new attachment objects to ensure we do not double-delete
     // See angle issue 686
@@ -648,9 +531,9 @@ DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colo
     mReadBufferState = GL_BACK;
 }
 
-int Framebuffer::getSamples() const
+int Framebuffer::getSamples(const gl::Data &data) const
 {
-    if (completeness() == GL_FRAMEBUFFER_COMPLETE)
+    if (completeness(data) == GL_FRAMEBUFFER_COMPLETE)
     {
         // for a complete framebuffer, all attachments must have the same sample count
         // in this case return the first nonzero sample size
@@ -675,7 +558,7 @@ bool Framebuffer::hasValidDepthStencil() const
             mDepthbuffer->id() == mStencilbuffer->id());
 }
 
-ColorbufferInfo Framebuffer::getColorbuffersForRender() const
+ColorbufferInfo Framebuffer::getColorbuffersForRender(const rx::Workarounds &workarounds) const
 {
     ColorbufferInfo colorbuffersForRender;
 
@@ -689,18 +572,78 @@ ColorbufferInfo Framebuffer::getColorbuffersForRender() const
             ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
             colorbuffersForRender.push_back(colorbuffer);
         }
-#if (ANGLE_MRT_PERF_WORKAROUND == ANGLE_WORKAROUND_DISABLED)
-        else
+        else if (!workarounds.mrtPerfWorkaround)
         {
             colorbuffersForRender.push_back(NULL);
         }
-#endif
     }
 
     return colorbuffersForRender;
 }
 
-GLenum DefaultFramebuffer::completeness() const
+void Framebuffer::setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex)
+{
+    setAttachment(attachment, new TextureAttachment(attachment, texture, imageIndex));
+}
+
+void Framebuffer::setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer)
+{
+    setAttachment(attachment, new RenderbufferAttachment(attachment, renderbuffer));
+}
+
+void Framebuffer::setNULLAttachment(GLenum attachment)
+{
+    setAttachment(attachment, NULL);
+}
+
+void Framebuffer::setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj)
+{
+    if (attachment >= GL_COLOR_ATTACHMENT0 && attachment < (GL_COLOR_ATTACHMENT0 + IMPLEMENTATION_MAX_DRAW_BUFFERS))
+    {
+        size_t colorAttachment = attachment - GL_COLOR_ATTACHMENT0;
+        SafeDelete(mColorbuffers[colorAttachment]);
+        mColorbuffers[colorAttachment] = attachmentObj;
+    }
+    else if (attachment == GL_DEPTH_ATTACHMENT)
+    {
+        SafeDelete(mDepthbuffer);
+        mDepthbuffer = attachmentObj;
+    }
+    else if (attachment == GL_STENCIL_ATTACHMENT)
+    {
+        SafeDelete(mStencilbuffer);
+        mStencilbuffer = attachmentObj;
+    }
+    else if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
+    {
+        SafeDelete(mDepthbuffer);
+        SafeDelete(mStencilbuffer);
+
+        // ensure this is a legitimate depth+stencil format
+        if (attachmentObj && attachmentObj->getDepthSize() > 0 && attachmentObj->getStencilSize() > 0)
+        {
+            mDepthbuffer = attachmentObj;
+
+            // Make a new attachment object to ensure we do not double-delete
+            // See angle issue 686
+            if (attachmentObj->isTexture())
+            {
+                mStencilbuffer = new TextureAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getTexture(),
+                                                       *attachmentObj->getTextureImageIndex());
+            }
+            else
+            {
+                mStencilbuffer = new RenderbufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getRenderbuffer());
+            }
+        }
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+}
+
+GLenum DefaultFramebuffer::completeness(const gl::Data &) const
 {
     // The default framebuffer *must* always be complete, though it may not be
     // subject to the same rules as application FBOs. ie, it could have 0x0 size.
diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h
index cc12d229537..d0fe8935ea8 100644
--- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h
@@ -10,41 +10,44 @@
 #ifndef LIBGLESV2_FRAMEBUFFER_H_
 #define LIBGLESV2_FRAMEBUFFER_H_
 
-#include <vector>
+#include "libGLESv2/Error.h"
 
 #include "common/angleutils.h"
 #include "common/RefCountObject.h"
-#include "constants.h"
+#include "Constants.h"
+
+#include <vector>
 
 namespace rx
 {
-class Renderer;
+class RenderbufferImpl;
+struct Workarounds;
 }
 
 namespace gl
 {
 class FramebufferAttachment;
-class Colorbuffer;
-class Depthbuffer;
-class Stencilbuffer;
-class DepthStencilbuffer;
+class Texture;
+class Renderbuffer;
+struct ImageIndex;
 struct Caps;
+struct Extensions;
+class TextureCapsMap;
+struct Data;
 
 typedef std::vector<FramebufferAttachment *> ColorbufferInfo;
 
 class Framebuffer
 {
   public:
-    Framebuffer(rx::Renderer *renderer, GLuint id);
-
+    Framebuffer(GLuint id);
     virtual ~Framebuffer();
 
     GLuint id() const { return mId; }
 
-    void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer);
-    void setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer);
-    void setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer);
-    void setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer);
+    void setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex);
+    void setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer);
+    void setNULLAttachment(GLenum attachment);
 
     void detachTexture(GLuint texture);
     void detachRenderbuffer(GLuint renderbuffer);
@@ -66,24 +69,21 @@ class Framebuffer
     bool isEnabledColorAttachment(unsigned int colorAttachment) const;
     bool hasEnabledColorAttachment() const;
     bool hasStencil() const;
-    int getSamples() const;
+    int getSamples(const gl::Data &data) const;
     bool usingExtendedDrawBuffers() const;
 
-    virtual GLenum completeness() const;
+    virtual GLenum completeness(const gl::Data &data) const;
     bool hasValidDepthStencil() const;
 
-    void invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments);
-    void invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments,
-                       GLint x, GLint y, GLsizei width, GLsizei height);
+    Error invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments);
+    Error invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
 
     // Use this method to retrieve the color buffer map when doing rendering.
     // It will apply a workaround for poor shader performance on some systems
     // by compacting the list to skip NULL values.
-    ColorbufferInfo getColorbuffersForRender() const;
+    ColorbufferInfo getColorbuffersForRender(const rx::Workarounds &workarounds) const;
 
   protected:
-    rx::Renderer *mRenderer;
-
     GLuint mId;
 
     FramebufferAttachment *mColorbuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
@@ -96,15 +96,15 @@ class Framebuffer
   private:
     DISALLOW_COPY_AND_ASSIGN(Framebuffer);
 
-    FramebufferAttachment *createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const;
+    void setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj);
 };
 
 class DefaultFramebuffer : public Framebuffer
 {
   public:
-    DefaultFramebuffer(rx::Renderer *Renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil);
+    DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil);
 
-    virtual GLenum completeness() const;
+    GLenum completeness(const gl::Data &data) const override;
     virtual FramebufferAttachment *getAttachment(GLenum attachment) const;
 
   private:
@@ -118,7 +118,7 @@ namespace rx
 class RenderTarget;
 
 // TODO: place this in FramebufferD3D.h
-RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment);
+gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT);
 unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment);
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp
index 540ede1cd2a..894884a6d88 100644
--- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp
@@ -187,7 +187,7 @@ GLenum RenderbufferAttachment::getActualFormat() const
 
 GLsizei RenderbufferAttachment::getSamples() const
 {
-    return mRenderbuffer->getStorage()->getSamples();
+    return mRenderbuffer->getSamples();
 }
 
 GLuint RenderbufferAttachment::id() const
diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h
index c18ef7364d7..8d2dafa7eee 100644
--- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h
+++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h
@@ -16,13 +16,6 @@
 
 #include "angle_gl.h"
 
-namespace rx
-{
-class Renderer;
-class RenderTarget;
-class TextureStorage;
-}
-
 namespace gl
 {
 class Renderbuffer;
diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp
index 3522b997e83..b45cd9c1696 100644
--- a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp
@@ -48,10 +48,101 @@ ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex)
     return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex);
 }
 
+ImageIndex ImageIndex::MakeInvalid()
+{
+    return ImageIndex(GL_NONE, -1, -1);
+}
+
 ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn)
     : type(typeIn),
       mipIndex(mipIndexIn),
       layerIndex(layerIndexIn)
 {}
 
+ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
+{
+    return ImageIndexIterator(GL_TEXTURE_2D, rx::Range<GLint>(minMip, maxMip),
+                              rx::Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), NULL);
+}
+
+ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
+{
+    return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, rx::Range<GLint>(minMip, maxMip), rx::Range<GLint>(0, 6), NULL);
+}
+
+ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip,
+                                              GLint minLayer, GLint maxLayer)
+{
+    return ImageIndexIterator(GL_TEXTURE_3D, rx::Range<GLint>(minMip, maxMip), rx::Range<GLint>(minLayer, maxLayer), NULL);
+}
+
+ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip,
+                                                   const GLsizei *layerCounts)
+{
+    return ImageIndexIterator(GL_TEXTURE_2D_ARRAY, rx::Range<GLint>(minMip, maxMip),
+                              rx::Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS), layerCounts);
+}
+
+ImageIndexIterator::ImageIndexIterator(GLenum type, const rx::Range<GLint> &mipRange,
+                                       const rx::Range<GLint> &layerRange, const GLsizei *layerCounts)
+    : mType(type),
+      mMipRange(mipRange),
+      mLayerRange(layerRange),
+      mLayerCounts(layerCounts),
+      mCurrentMip(mipRange.start),
+      mCurrentLayer(layerRange.start)
+{}
+
+GLint ImageIndexIterator::maxLayer() const
+{
+    return (mLayerCounts ? static_cast<GLint>(mLayerCounts[mCurrentMip]) : mLayerRange.end);
+}
+
+ImageIndex ImageIndexIterator::next()
+{
+    ASSERT(hasNext());
+
+    ImageIndex value = current();
+
+    // Iterate layers in the inner loop for now. We can add switchable
+    // layer or mip iteration if we need it.
+
+    if (mCurrentLayer != ImageIndex::ENTIRE_LEVEL)
+    {
+        if (mCurrentLayer < maxLayer()-1)
+        {
+            mCurrentLayer++;
+        }
+        else if (mCurrentMip < mMipRange.end-1)
+        {
+            mCurrentMip++;
+            mCurrentLayer = mLayerRange.start;
+        }
+    }
+    else if (mCurrentMip < mMipRange.end-1)
+    {
+        mCurrentMip++;
+        mCurrentLayer = mLayerRange.start;
+    }
+
+    return value;
+}
+
+ImageIndex ImageIndexIterator::current() const
+{
+    ImageIndex value(mType, mCurrentMip, mCurrentLayer);
+
+    if (mType == GL_TEXTURE_CUBE_MAP)
+    {
+        value.type = TextureCubeMap::layerIndexToTarget(mCurrentLayer);
+    }
+
+    return value;
+}
+
+bool ImageIndexIterator::hasNext() const
+{
+    return (mCurrentMip < mMipRange.end || mCurrentLayer < maxLayer());
+}
+
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h b/src/3rdparty/angle/src/libGLESv2/ImageIndex.h
index 9f2df88061b..8bb14fd5554 100644
--- a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h
+++ b/src/3rdparty/angle/src/libGLESv2/ImageIndex.h
@@ -10,6 +10,7 @@
 #define LIBGLESV2_IMAGE_INDEX_H_
 
 #include "angle_gl.h"
+#include "common/mathutil.h"
 
 namespace gl
 {
@@ -20,6 +21,7 @@ struct ImageIndex
     GLint mipIndex;
     GLint layerIndex;
 
+    ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn);
     ImageIndex(const ImageIndex &other);
     ImageIndex &operator=(const ImageIndex &other);
 
@@ -29,11 +31,36 @@ struct ImageIndex
     static ImageIndex MakeCube(GLenum target, GLint mipIndex);
     static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex);
     static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL);
+    static ImageIndex MakeInvalid();
 
     static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1);
+};
+
+class ImageIndexIterator
+{
+  public:
+    static ImageIndexIterator Make2D(GLint minMip, GLint maxMip);
+    static ImageIndexIterator MakeCube(GLint minMip, GLint maxMip);
+    static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer);
+    static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts);
+
+    ImageIndex next();
+    ImageIndex current() const;
+    bool hasNext() const;
 
   private:
-    ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn);
+
+    ImageIndexIterator(GLenum type, const rx::Range<GLint> &mipRange,
+                       const rx::Range<GLint> &layerRange, const GLsizei *layerCounts);
+
+    GLint maxLayer() const;
+
+    GLenum mType;
+    rx::Range<GLint> mMipRange;
+    rx::Range<GLint> mLayerRange;
+    const GLsizei *mLayerCounts;
+    GLint mCurrentMip;
+    GLint mCurrentLayer;
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp
index 9bfda09a647..3faa8c56f6f 100644
--- a/src/3rdparty/angle/src/libGLESv2/Program.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Program.cpp
@@ -244,7 +244,7 @@ void Program::bindAttributeLocation(GLuint index, const char *name)
 // Links the HLSL code of the vertex and pixel shader by matching up their varyings,
 // compiling them into binaries, determining the attribute mappings, and collecting
 // a list of uniforms
-bool Program::link(const Caps &caps)
+Error Program::link(const Data &data)
 {
     unlink(false);
 
@@ -252,10 +252,15 @@ bool Program::link(const Caps &caps)
     resetUniformBlockBindings();
 
     mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
-    mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
-                                   mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps);
+    LinkResult result = mProgramBinary->link(data, mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
+                                             mTransformFeedbackVaryings, mTransformFeedbackBufferMode);
+    if (result.error.isError())
+    {
+        return result.error;
+    }
 
-    return mLinked;
+    mLinked = result.linkSuccess;
+    return gl::Error(GL_NO_ERROR);
 }
 
 int AttributeBindings::getAttributeBinding(const std::string &name) const
@@ -303,21 +308,22 @@ ProgramBinary* Program::getProgramBinary() const
     return mProgramBinary.get();
 }
 
-bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
+Error Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
 {
     unlink(false);
 
     mInfoLog.reset();
 
     mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
-    mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
-
-    if (!mLinked)
+    LinkResult result = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
+    if (result.error.isError())
     {
         mProgramBinary.set(NULL);
+        return result.error;
     }
 
-    return mLinked;
+    mLinked = result.linkSuccess;
+    return Error(GL_NO_ERROR);
 }
 
 void Program::release()
diff --git a/src/3rdparty/angle/src/libGLESv2/Program.h b/src/3rdparty/angle/src/libGLESv2/Program.h
index 6528dd11914..b92349eeefb 100644
--- a/src/3rdparty/angle/src/libGLESv2/Program.h
+++ b/src/3rdparty/angle/src/libGLESv2/Program.h
@@ -29,6 +29,7 @@ class Renderer;
 namespace gl
 {
 struct Caps;
+struct Data;
 class ResourceManager;
 class Shader;
 
@@ -77,9 +78,9 @@ class Program
 
     void bindAttributeLocation(GLuint index, const char *name);
 
-    bool link(const Caps &caps);
+    Error link(const Data &data);
     bool isLinked();
-    bool setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length);
+    Error setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length);
     ProgramBinary *getProgramBinary() const;
 
     int getInfoLogLength() const;
diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
index 3f6d9e0ef9c..6d64b38b566 100644
--- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
@@ -23,13 +23,11 @@
 #include "libGLESv2/Shader.h"
 #include "libGLESv2/Program.h"
 #include "libGLESv2/renderer/ProgramImpl.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/d3d/DynamicHLSL.h"
 #include "libGLESv2/renderer/d3d/ShaderD3D.h"
-#include "libGLESv2/renderer/d3d/VertexDataManager.h"
 #include "libGLESv2/Context.h"
 #include "libGLESv2/Buffer.h"
 #include "common/blocklayout.h"
+#include "common/features.h"
 
 namespace gl
 {
@@ -37,36 +35,6 @@ namespace gl
 namespace
 {
 
-GLenum GetTextureType(GLenum samplerType)
-{
-    switch (samplerType)
-    {
-      case GL_SAMPLER_2D:
-      case GL_INT_SAMPLER_2D:
-      case GL_UNSIGNED_INT_SAMPLER_2D:
-      case GL_SAMPLER_2D_SHADOW:
-        return GL_TEXTURE_2D;
-      case GL_SAMPLER_3D:
-      case GL_INT_SAMPLER_3D:
-      case GL_UNSIGNED_INT_SAMPLER_3D:
-        return GL_TEXTURE_3D;
-      case GL_SAMPLER_CUBE:
-      case GL_SAMPLER_CUBE_SHADOW:
-        return GL_TEXTURE_CUBE_MAP;
-      case GL_INT_SAMPLER_CUBE:
-      case GL_UNSIGNED_INT_SAMPLER_CUBE:
-        return GL_TEXTURE_CUBE_MAP;
-      case GL_SAMPLER_2D_ARRAY:
-      case GL_INT_SAMPLER_2D_ARRAY:
-      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
-      case GL_SAMPLER_2D_ARRAY_SHADOW:
-        return GL_TEXTURE_2D_ARRAY;
-      default: UNREACHABLE();
-    }
-
-    return GL_TEXTURE_2D;
-}
-
 unsigned int ParseAndStripArrayIndex(std::string* name)
 {
     unsigned int subscript = GL_INVALID_INDEX;
@@ -83,52 +51,6 @@ unsigned int ParseAndStripArrayIndex(std::string* name)
     return subscript;
 }
 
-void GetDefaultInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])
-{
-    size_t layoutIndex = 0;
-    for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
-    {
-        ASSERT(layoutIndex < MAX_VERTEX_ATTRIBS);
-
-        const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex];
-
-        if (shaderAttr.type != GL_NONE)
-        {
-            GLenum transposedType = TransposeMatrixType(shaderAttr.type);
-
-            for (size_t rowIndex = 0; static_cast<int>(rowIndex) < VariableRowCount(transposedType); rowIndex++, layoutIndex++)
-            {
-                VertexFormat *defaultFormat = &inputLayout[layoutIndex];
-
-                defaultFormat->mType = VariableComponentType(transposedType);
-                defaultFormat->mNormalized = false;
-                defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool
-                defaultFormat->mComponents = VariableColumnCount(transposedType);
-            }
-        }
-    }
-}
-
-std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<rx::PixelShaderOutputVariable> &shaderOutputVars)
-{
-    std::vector<GLenum> defaultPixelOutput(1);
-
-    ASSERT(!shaderOutputVars.empty());
-    defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex;
-
-    return defaultPixelOutput;
-}
-
-bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
-{
-    return var.isRowMajorLayout;
-}
-
-bool IsRowMajorLayout(const sh::ShaderVariable &var)
-{
-    return false;
-}
-
 }
 
 VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
@@ -136,47 +58,6 @@ VariableLocation::VariableLocation(const std::string &name, unsigned int element
 {
 }
 
-ProgramBinary::VertexExecutable::VertexExecutable(const VertexFormat inputLayout[],
-                                                  const GLenum signature[],
-                                                  rx::ShaderExecutable *shaderExecutable)
-    : mShaderExecutable(shaderExecutable)
-{
-    for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
-    {
-        mInputs[attributeIndex] = inputLayout[attributeIndex];
-        mSignature[attributeIndex] = signature[attributeIndex];
-    }
-}
-
-ProgramBinary::VertexExecutable::~VertexExecutable()
-{
-    SafeDelete(mShaderExecutable);
-}
-
-bool ProgramBinary::VertexExecutable::matchesSignature(const GLenum signature[]) const
-{
-    for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
-    {
-        if (mSignature[attributeIndex] != signature[attributeIndex])
-        {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-ProgramBinary::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable)
-    : mOutputSignature(outputSignature),
-      mShaderExecutable(shaderExecutable)
-{
-}
-
-ProgramBinary::PixelExecutable::~PixelExecutable()
-{
-    SafeDelete(mShaderExecutable);
-}
-
 LinkedVarying::LinkedVarying()
 {
 }
@@ -187,17 +68,17 @@ LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size,
 {
 }
 
+LinkResult::LinkResult(bool linkSuccess, const Error &error)
+    : linkSuccess(linkSuccess),
+      error(error)
+{
+}
+
 unsigned int ProgramBinary::mCurrentSerial = 1;
 
 ProgramBinary::ProgramBinary(rx::ProgramImpl *impl)
     : RefCountObject(0),
       mProgram(impl),
-      mGeometryExecutable(NULL),
-      mUsedVertexSamplerRange(0),
-      mUsedPixelSamplerRange(0),
-      mUsesPointSize(false),
-      mShaderVersion(100),
-      mDirtySamplerMapping(true),
       mValidated(false),
       mSerial(issueSerial())
 {
@@ -220,103 +101,11 @@ unsigned int ProgramBinary::getSerial() const
     return mSerial;
 }
 
-int ProgramBinary::getShaderVersion() const
-{
-    return mShaderVersion;
-}
-
 unsigned int ProgramBinary::issueSerial()
 {
     return mCurrentSerial++;
 }
 
-rx::ShaderExecutable *ProgramBinary::getPixelExecutableForFramebuffer(const Framebuffer *fbo)
-{
-    std::vector<GLenum> outputs;
-
-    const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender();
-
-    for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
-    {
-        const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
-
-        if (colorbuffer)
-        {
-            outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
-        }
-        else
-        {
-            outputs.push_back(GL_NONE);
-        }
-    }
-
-    return getPixelExecutableForOutputLayout(outputs);
-}
-
-rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature)
-{
-    for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
-    {
-        if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
-        {
-            return mPixelExecutables[executableIndex]->shaderExecutable();
-        }
-    }
-
-    InfoLog tempInfoLog;
-    rx::ShaderExecutable *pixelExecutable = mProgram->getPixelExecutableForOutputLayout(tempInfoLog, outputSignature,
-            mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
-
-    if (!pixelExecutable)
-    {
-        std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
-        tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
-        ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
-    }
-    else
-    {
-        mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
-    }
-
-    return pixelExecutable;
-}
-
-rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])
-{
-    GLenum signature[MAX_VERTEX_ATTRIBS];
-    mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature);
-
-    for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
-    {
-        if (mVertexExecutables[executableIndex]->matchesSignature(signature))
-        {
-            return mVertexExecutables[executableIndex]->shaderExecutable();
-        }
-    }
-
-    InfoLog tempInfoLog;
-    rx::ShaderExecutable *vertexExecutable = mProgram->getVertexExecutableForInputLayout(tempInfoLog, inputLayout, mShaderAttributes,
-            mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
-
-    if (!vertexExecutable)
-    {
-        std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
-        tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
-        ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
-    }
-    else
-    {
-        mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable));
-    }
-
-    return vertexExecutable;
-}
-
-rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() const
-{
-    return mGeometryExecutable;
-}
-
 GLuint ProgramBinary::getAttributeLocation(const char *name)
 {
     if (name)
@@ -343,157 +132,42 @@ int ProgramBinary::getSemanticIndex(int attributeIndex)
 // Returns one more than the highest sampler index used.
 GLint ProgramBinary::getUsedSamplerRange(SamplerType type)
 {
-    switch (type)
-    {
-      case SAMPLER_PIXEL:
-        return mUsedPixelSamplerRange;
-      case SAMPLER_VERTEX:
-        return mUsedVertexSamplerRange;
-      default:
-        UNREACHABLE();
-        return 0;
-    }
+    return mProgram->getUsedSamplerRange(type);
 }
 
 bool ProgramBinary::usesPointSize() const
 {
-    return mUsesPointSize;
-}
-
-bool ProgramBinary::usesPointSpriteEmulation() const
-{
-    return mUsesPointSize && mProgram->getRenderer()->getMajorShaderModel() >= 4;
-}
-
-bool ProgramBinary::usesGeometryShader() const
-{
-    return usesPointSpriteEmulation();
+    return mProgram->usesPointSize();
 }
 
 GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps)
 {
-    GLint logicalTextureUnit = -1;
-
-    switch (type)
-    {
-      case SAMPLER_PIXEL:
-        ASSERT(samplerIndex < caps.maxTextureImageUnits);
-        if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
-        {
-            logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
-        }
-        break;
-      case SAMPLER_VERTEX:
-        ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
-        if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
-        {
-            logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
-        }
-        break;
-      default: UNREACHABLE();
-    }
-
-    if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
-    {
-        return logicalTextureUnit;
-    }
-
-    return -1;
+    return mProgram->getSamplerMapping(type, samplerIndex, caps);
 }
 
-// Returns the texture type for a given Direct3D 9 sampler type and
-// index (0-15 for the pixel shader and 0-3 for the vertex shader).
 GLenum ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
 {
-    switch (type)
-    {
-      case SAMPLER_PIXEL:
-        ASSERT(samplerIndex < mSamplersPS.size());
-        ASSERT(mSamplersPS[samplerIndex].active);
-        return mSamplersPS[samplerIndex].textureType;
-      case SAMPLER_VERTEX:
-        ASSERT(samplerIndex < mSamplersVS.size());
-        ASSERT(mSamplersVS[samplerIndex].active);
-        return mSamplersVS[samplerIndex].textureType;
-      default: UNREACHABLE();
-    }
-
-    return GL_TEXTURE_2D;
+    return mProgram->getSamplerTextureType(type, samplerIndex);
 }
 
 GLint ProgramBinary::getUniformLocation(std::string name)
 {
-    unsigned int subscript = ParseAndStripArrayIndex(&name);
-
-    unsigned int numUniforms = mUniformIndex.size();
-    for (unsigned int location = 0; location < numUniforms; location++)
-    {
-        if (mUniformIndex[location].name == name)
-        {
-            const int index = mUniformIndex[location].index;
-            const bool isArray = mUniforms[index]->isArray();
-
-            if ((isArray && mUniformIndex[location].element == subscript) ||
-                (subscript == GL_INVALID_INDEX))
-            {
-                return location;
-            }
-        }
-    }
-
-    return -1;
+    return mProgram->getUniformLocation(name);
 }
 
 GLuint ProgramBinary::getUniformIndex(std::string name)
 {
-    unsigned int subscript = ParseAndStripArrayIndex(&name);
-
-    // The app is not allowed to specify array indices other than 0 for arrays of basic types
-    if (subscript != 0 && subscript != GL_INVALID_INDEX)
-    {
-        return GL_INVALID_INDEX;
-    }
-
-    unsigned int numUniforms = mUniforms.size();
-    for (unsigned int index = 0; index < numUniforms; index++)
-    {
-        if (mUniforms[index]->name == name)
-        {
-            if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX)
-            {
-                return index;
-            }
-        }
-    }
-
-    return GL_INVALID_INDEX;
+    return mProgram->getUniformIndex(name);
 }
 
 GLuint ProgramBinary::getUniformBlockIndex(std::string name)
 {
-    unsigned int subscript = ParseAndStripArrayIndex(&name);
-
-    unsigned int numUniformBlocks = mUniformBlocks.size();
-    for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
-    {
-        const UniformBlock &uniformBlock = *mUniformBlocks[blockIndex];
-        if (uniformBlock.name == name)
-        {
-            const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0);
-            if (subscript == uniformBlock.elementIndex || arrayElementZero)
-            {
-                return blockIndex;
-            }
-        }
-    }
-
-    return GL_INVALID_INDEX;
+    return mProgram->getUniformBlockIndex(name);
 }
 
 UniformBlock *ProgramBinary::getUniformBlockByIndex(GLuint blockIndex)
 {
-    ASSERT(blockIndex < mUniformBlocks.size());
-    return mUniformBlocks[blockIndex];
+    return mProgram->getUniformBlockByIndex(blockIndex);
 }
 
 GLint ProgramBinary::getFragDataLocation(const char *name) const
@@ -517,524 +191,129 @@ GLint ProgramBinary::getFragDataLocation(const char *name) const
 
 size_t ProgramBinary::getTransformFeedbackVaryingCount() const
 {
-    return mTransformFeedbackLinkedVaryings.size();
+    return mProgram->getTransformFeedbackLinkedVaryings().size();
 }
 
 const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const
 {
-    return mTransformFeedbackLinkedVaryings[idx];
+    return mProgram->getTransformFeedbackLinkedVaryings()[idx];
 }
 
 GLenum ProgramBinary::getTransformFeedbackBufferMode() const
 {
-    return mTransformFeedbackBufferMode;
+    return mProgram->getTransformFeedbackBufferMode();
 }
 
-template <typename T>
-static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
-{
-    ASSERT(dest != NULL);
-    ASSERT(dirtyFlag != NULL);
-
-    *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
-    *dest = source;
+void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) {
+    mProgram->setUniform1fv(location, count, v);
 }
 
-template <typename T>
-void ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType)
-{
-    const int components = VariableComponentCount(targetUniformType);
-    const GLenum targetBoolType = VariableBoolVectorType(targetUniformType);
-
-    LinkedUniform *targetUniform = getUniformByLocation(location);
-
-    int elementCount = targetUniform->elementCount();
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-
-    if (targetUniform->type == targetUniformType)
-    {
-        T *target = reinterpret_cast<T*>(targetUniform->data) + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            T *dest = target + (i * 4);
-            const T *source = v + (i * components);
-
-            for (int c = 0; c < components; c++)
-            {
-                SetIfDirty(dest + c, source[c], &targetUniform->dirty);
-            }
-            for (int c = components; c < 4; c++)
-            {
-                SetIfDirty(dest + c, T(0), &targetUniform->dirty);
-            }
-        }
-    }
-    else if (targetUniform->type == targetBoolType)
-    {
-        GLint *boolParams = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            GLint *dest = boolParams + (i * 4);
-            const T *source = v + (i * components);
-
-            for (int c = 0; c < components; c++)
-            {
-                SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
-            }
-            for (int c = components; c < 4; c++)
-            {
-                SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
-            }
-        }
-    }
-    else if (IsSampler(targetUniform->type))
-    {
-        ASSERT(targetUniformType == GL_INT);
-
-        GLint *target = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
+void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) {
+    mProgram->setUniform2fv(location, count, v);
+}
 
-        bool wasDirty = targetUniform->dirty;
+void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) {
+    mProgram->setUniform3fv(location, count, v);
+}
 
-        for (int i = 0; i < count; i++)
-        {
-            GLint *dest = target + (i * 4);
-            const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components);
+void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) {
+    mProgram->setUniform4fv(location, count, v);
+}
 
-            SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
-            SetIfDirty(dest + 1, 0, &targetUniform->dirty);
-            SetIfDirty(dest + 2, 0, &targetUniform->dirty);
-            SetIfDirty(dest + 3, 0, &targetUniform->dirty);
-        }
+void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) {
+    mProgram->setUniform1iv(location, count, v);
+}
 
-        if (!wasDirty && targetUniform->dirty)
-        {
-            mDirtySamplerMapping = true;
-        }
-    }
-    else UNREACHABLE();
+void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) {
+    mProgram->setUniform2iv(location, count, v);
 }
 
-void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
-{
-    setUniform(location, count, v, GL_FLOAT);
+void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) {
+    mProgram->setUniform3iv(location, count, v);
 }
 
-void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
-{
-    setUniform(location, count, v, GL_FLOAT_VEC2);
+void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) {
+    mProgram->setUniform4iv(location, count, v);
 }
 
-void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
-{
-    setUniform(location, count, v, GL_FLOAT_VEC3);
+void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) {
+    mProgram->setUniform1uiv(location, count, v);
 }
 
-void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
-{
-    setUniform(location, count, v, GL_FLOAT_VEC4);
+void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) {
+    mProgram->setUniform2uiv(location, count, v);
 }
 
-template<typename T>
-bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
-{
-    bool dirty = false;
-    int copyWidth = std::min(targetHeight, srcWidth);
-    int copyHeight = std::min(targetWidth, srcHeight);
+void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) {
+    mProgram->setUniform3uiv(location, count, v);
+}
 
-    for (int x = 0; x < copyWidth; x++)
-    {
-        for (int y = 0; y < copyHeight; y++)
-        {
-            SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty);
-        }
-    }
-    // clear unfilled right side
-    for (int y = 0; y < copyWidth; y++)
-    {
-        for (int x = copyHeight; x < targetWidth; x++)
-        {
-            SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
-        }
-    }
-    // clear unfilled bottom.
-    for (int y = copyWidth; y < targetHeight; y++)
-    {
-        for (int x = 0; x < targetWidth; x++)
-        {
-            SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
-        }
-    }
+void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) {
+    mProgram->setUniform4uiv(location, count, v);
+}
 
-    return dirty;
+void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
+    mProgram->setUniformMatrix2fv(location, count, transpose, v);
 }
 
-template<typename T>
-bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
-{
-    bool dirty = false;
-    int copyWidth = std::min(targetWidth, srcWidth);
-    int copyHeight = std::min(targetHeight, srcHeight);
+void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
+    mProgram->setUniformMatrix3fv(location, count, transpose, v);
+}
 
-    for (int y = 0; y < copyHeight; y++)
-    {
-        for (int x = 0; x < copyWidth; x++)
-        {
-            SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty);
-        }
-    }
-    // clear unfilled right side
-    for (int y = 0; y < copyHeight; y++)
-    {
-        for (int x = copyWidth; x < targetWidth; x++)
-        {
-            SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
-        }
-    }
-    // clear unfilled bottom.
-    for (int y = copyHeight; y < targetHeight; y++)
-    {
-        for (int x = 0; x < targetWidth; x++)
-        {
-            SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
-        }
-    }
+void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
+    mProgram->setUniformMatrix4fv(location, count, transpose, v);
+}
 
-    return dirty;
+void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
+    mProgram->setUniformMatrix2x3fv(location, count, transpose, v);
 }
 
-template <int cols, int rows>
-void ProgramBinary::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType)
-{
-    LinkedUniform *targetUniform = getUniformByLocation(location);
+void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
+    mProgram->setUniformMatrix2x4fv(location, count, transpose, v);
+}
 
-    int elementCount = targetUniform->elementCount();
+void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
+    mProgram->setUniformMatrix3x2fv(location, count, transpose, v);
+}
 
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-    const unsigned int targetMatrixStride = (4 * rows);
-    GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride);
+void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
+    mProgram->setUniformMatrix3x4fv(location, count, transpose, v);
+}
 
-    for (int i = 0; i < count; i++)
-    {
-        // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
-        if (transpose == GL_FALSE)
-        {
-            targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty;
-        }
-        else
-        {
-            targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
-        }
-        target += targetMatrixStride;
-        value += cols * rows;
-    }
+void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
+    mProgram->setUniformMatrix4x2fv(location, count, transpose, v);
 }
 
-void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
-{
-    setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
+void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
+    mProgram->setUniformMatrix4x3fv(location, count, transpose, v);
 }
 
-void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
-{
-    setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
+void ProgramBinary::getUniformfv(GLint location, GLfloat *v) {
+    mProgram->getUniformfv(location, v);
 }
 
-void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
-{
-    setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
+void ProgramBinary::getUniformiv(GLint location, GLint *v) {
+    mProgram->getUniformiv(location, v);
 }
 
-void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
-{
-    setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
+void ProgramBinary::getUniformuiv(GLint location, GLuint *v) {
+    mProgram->getUniformuiv(location, v);
 }
 
-void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+void ProgramBinary::updateSamplerMapping()
 {
-    setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
+    return mProgram->updateSamplerMapping();
 }
 
-void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+// Applies all the uniforms set for this program object to the renderer
+Error ProgramBinary::applyUniforms()
 {
-    setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
+    return mProgram->applyUniforms();
 }
 
-void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+Error ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const Caps &caps)
 {
-    setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
-}
-
-void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
-{
-    setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
-}
-
-void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
-{
-    setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
-}
-
-void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)
-{
-    setUniform(location, count, v, GL_INT);
-}
-
-void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v)
-{
-    setUniform(location, count, v, GL_INT_VEC2);
-}
-
-void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v)
-{
-    setUniform(location, count, v, GL_INT_VEC3);
-}
-
-void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v)
-{
-    setUniform(location, count, v, GL_INT_VEC4);
-}
-
-void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
-{
-    setUniform(location, count, v, GL_UNSIGNED_INT);
-}
-
-void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
-{
-    setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
-}
-
-void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
-{
-    setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
-}
-
-void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
-{
-    setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
-}
-
-template <typename T>
-void ProgramBinary::getUniformv(GLint location, T *params, GLenum uniformType)
-{
-    LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    if (IsMatrixType(targetUniform->type))
-    {
-        const int rows = VariableRowCount(targetUniform->type);
-        const int cols = VariableColumnCount(targetUniform->type);
-        transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows);
-    }
-    else if (uniformType == VariableComponentType(targetUniform->type))
-    {
-        unsigned int size = VariableComponentCount(targetUniform->type);
-        memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T),
-                size * sizeof(T));
-    }
-    else
-    {
-        unsigned int size = VariableComponentCount(targetUniform->type);
-        switch (VariableComponentType(targetUniform->type))
-        {
-          case GL_BOOL:
-            {
-                GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-                for (unsigned int i = 0; i < size; i++)
-                {
-                    params[i] = (boolParams[i] == GL_FALSE) ? static_cast<T>(0) : static_cast<T>(1);
-                }
-            }
-            break;
-
-          case GL_FLOAT:
-            {
-                GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
-
-                for (unsigned int i = 0; i < size; i++)
-                {
-                    params[i] = static_cast<T>(floatParams[i]);
-                }
-            }
-            break;
-
-          case GL_INT:
-            {
-                GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-                for (unsigned int i = 0; i < size; i++)
-                {
-                    params[i] = static_cast<T>(intParams[i]);
-                }
-            }
-            break;
-
-          case GL_UNSIGNED_INT:
-            {
-                GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-                for (unsigned int i = 0; i < size; i++)
-                {
-                    params[i] = static_cast<T>(uintParams[i]);
-                }
-            }
-            break;
-
-          default: UNREACHABLE();
-        }
-    }
-}
-
-void ProgramBinary::getUniformfv(GLint location, GLfloat *params)
-{
-    getUniformv(location, params, GL_FLOAT);
-}
-
-void ProgramBinary::getUniformiv(GLint location, GLint *params)
-{
-    getUniformv(location, params, GL_INT);
-}
-
-void ProgramBinary::getUniformuiv(GLint location, GLuint *params)
-{
-    getUniformv(location, params, GL_UNSIGNED_INT);
-}
-
-void ProgramBinary::dirtyAllUniforms()
-{
-    unsigned int numUniforms = mUniforms.size();
-    for (unsigned int index = 0; index < numUniforms; index++)
-    {
-        mUniforms[index]->dirty = true;
-    }
-}
-
-void ProgramBinary::updateSamplerMapping()
-{
-    if (!mDirtySamplerMapping)
-    {
-        return;
-    }
-
-    mDirtySamplerMapping = false;
-
-    // Retrieve sampler uniform values
-    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
-    {
-        LinkedUniform *targetUniform = mUniforms[uniformIndex];
-
-        if (targetUniform->dirty)
-        {
-            if (IsSampler(targetUniform->type))
-            {
-                int count = targetUniform->elementCount();
-                GLint (*v)[4] = reinterpret_cast<GLint(*)[4]>(targetUniform->data);
-
-                if (targetUniform->isReferencedByFragmentShader())
-                {
-                    unsigned int firstIndex = targetUniform->psRegisterIndex;
-
-                    for (int i = 0; i < count; i++)
-                    {
-                        unsigned int samplerIndex = firstIndex + i;
-
-                        if (samplerIndex < mSamplersPS.size())
-                        {
-                            ASSERT(mSamplersPS[samplerIndex].active);
-                            mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
-                        }
-                    }
-                }
-
-                if (targetUniform->isReferencedByVertexShader())
-                {
-                    unsigned int firstIndex = targetUniform->vsRegisterIndex;
-
-                    for (int i = 0; i < count; i++)
-                    {
-                        unsigned int samplerIndex = firstIndex + i;
-
-                        if (samplerIndex < mSamplersVS.size())
-                        {
-                            ASSERT(mSamplersVS[samplerIndex].active);
-                            mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-// Applies all the uniforms set for this program object to the renderer
-Error ProgramBinary::applyUniforms()
-{
-    updateSamplerMapping();
-
-    Error error = mProgram->getRenderer()->applyUniforms(*this);
-    if (error.isError())
-    {
-        return error;
-    }
-
-    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
-    {
-        mUniforms[uniformIndex]->dirty = false;
-    }
-
-    return gl::Error(GL_NO_ERROR);
-}
-
-Error ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const Caps &caps)
-{
-    const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL};
-    const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL};
-
-    const unsigned int reservedBuffersInVS = mProgram->getRenderer()->getReservedVertexUniformBuffers();
-    const unsigned int reservedBuffersInFS = mProgram->getRenderer()->getReservedFragmentUniformBuffers();
-
-    ASSERT(boundBuffers.size() == mUniformBlocks.size());
-
-    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++)
-    {
-        UniformBlock *uniformBlock = getUniformBlockByIndex(uniformBlockIndex);
-        gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex];
-
-        ASSERT(uniformBlock && uniformBuffer);
-
-        if (uniformBuffer->getSize() < uniformBlock->dataSize)
-        {
-            // undefined behaviour
-            return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small.");
-        }
-
-        // Unnecessary to apply an unreferenced standard or shared UBO
-        if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader())
-        {
-            continue;
-        }
-
-        if (uniformBlock->isReferencedByVertexShader())
-        {
-            unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
-            ASSERT(vertexUniformBuffers[registerIndex] == NULL);
-            ASSERT(registerIndex < caps.maxVertexUniformBlocks);
-            vertexUniformBuffers[registerIndex] = uniformBuffer;
-        }
-
-        if (uniformBlock->isReferencedByFragmentShader())
-        {
-            unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
-            ASSERT(fragmentUniformBuffers[registerIndex] == NULL);
-            ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
-            fragmentUniformBuffers[registerIndex] = uniformBuffer;
-        }
-    }
-
-    return mProgram->getRenderer()->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
+    return mProgram->applyUniformBuffers(boundBuffers, caps);
 }
 
 bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader)
@@ -1082,10 +361,10 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shade
     return true;
 }
 
-bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length)
+LinkResult ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length)
 {
-#ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
-    return false;
+#if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_DISABLED
+    return LinkResult(false, Error(GL_NO_ERROR));
 #else
     ASSERT(binaryFormat == mProgram->getBinaryFormat());
 
@@ -1097,7 +376,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
     if (format != mProgram->getBinaryFormat())
     {
         infoLog.append("Invalid program binary format.");
-        return false;
+        return LinkResult(false, Error(GL_NO_ERROR));
     }
 
     int majorVersion = stream.readInt<int>();
@@ -1105,7 +384,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
     if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
     {
         infoLog.append("Invalid program binary version.");
-        return false;
+        return LinkResult(false, Error(GL_NO_ERROR));
     }
 
     unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
@@ -1113,562 +392,277 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina
     if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0)
     {
         infoLog.append("Invalid program binary version.");
-        return false;
+        return LinkResult(false, Error(GL_NO_ERROR));
     }
 
     int compileFlags = stream.readInt<int>();
     if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
     {
         infoLog.append("Mismatched compilation flags.");
-        return false;
+        return LinkResult(false, Error(GL_NO_ERROR));
     }
 
     for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
     {
         stream.readInt(&mLinkedAttribute[i].type);
         stream.readString(&mLinkedAttribute[i].name);
-        stream.readInt(&mShaderAttributes[i].type);
-        stream.readString(&mShaderAttributes[i].name);
+        stream.readInt(&mProgram->getShaderAttributes()[i].type);
+        stream.readString(&mProgram->getShaderAttributes()[i].name);
         stream.readInt(&mSemanticIndex[i]);
     }
 
     initAttributesByLayout();
 
-    const unsigned int psSamplerCount = stream.readInt<unsigned int>();
-    for (unsigned int i = 0; i < psSamplerCount; ++i)
-    {
-        Sampler sampler;
-        stream.readBool(&sampler.active);
-        stream.readInt(&sampler.logicalTextureUnit);
-        stream.readInt(&sampler.textureType);
-        mSamplersPS.push_back(sampler);
-    }
-    const unsigned int vsSamplerCount = stream.readInt<unsigned int>();
-    for (unsigned int i = 0; i < vsSamplerCount; ++i)
+    LinkResult result = mProgram->load(infoLog, &stream);
+    if (result.error.isError() || !result.linkSuccess)
     {
-        Sampler sampler;
-        stream.readBool(&sampler.active);
-        stream.readInt(&sampler.logicalTextureUnit);
-        stream.readInt(&sampler.textureType);
-        mSamplersVS.push_back(sampler);
+        return result;
     }
 
-    stream.readInt(&mUsedVertexSamplerRange);
-    stream.readInt(&mUsedPixelSamplerRange);
-    stream.readBool(&mUsesPointSize);
-    stream.readInt(&mShaderVersion);
+    return LinkResult(true, Error(GL_NO_ERROR));
+#endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
+}
 
-    const unsigned int uniformCount = stream.readInt<unsigned int>();
-    if (stream.error())
+Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length)
+{
+    if (binaryFormat)
     {
-        infoLog.append("Invalid program binary.");
-        return false;
+        *binaryFormat = mProgram->getBinaryFormat();
     }
 
-    mUniforms.resize(uniformCount);
-    for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
-    {
-        GLenum type = stream.readInt<GLenum>();
-        GLenum precision = stream.readInt<GLenum>();
-        std::string name = stream.readString();
-        unsigned int arraySize = stream.readInt<unsigned int>();
-        int blockIndex = stream.readInt<int>();
-
-        int offset = stream.readInt<int>();
-        int arrayStride = stream.readInt<int>();
-        int matrixStride = stream.readInt<int>();
-        bool isRowMajorMatrix = stream.readBool();
-
-        const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix);
-
-        LinkedUniform *uniform = new LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo);
-
-        stream.readInt(&uniform->psRegisterIndex);
-        stream.readInt(&uniform->vsRegisterIndex);
-        stream.readInt(&uniform->registerCount);
-        stream.readInt(&uniform->registerElement);
+    BinaryOutputStream stream;
 
-        mUniforms[uniformIndex] = uniform;
-    }
+    stream.writeInt(mProgram->getBinaryFormat());
+    stream.writeInt(ANGLE_MAJOR_VERSION);
+    stream.writeInt(ANGLE_MINOR_VERSION);
+    stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
+    stream.writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
 
-    unsigned int uniformBlockCount = stream.readInt<unsigned int>();
-    if (stream.error())
+    for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
     {
-        infoLog.append("Invalid program binary.");
-        return false;
+        stream.writeInt(mLinkedAttribute[i].type);
+        stream.writeString(mLinkedAttribute[i].name);
+        stream.writeInt(mProgram->getShaderAttributes()[i].type);
+        stream.writeString(mProgram->getShaderAttributes()[i].name);
+        stream.writeInt(mSemanticIndex[i]);
     }
 
-    mUniformBlocks.resize(uniformBlockCount);
-    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
-    {
-        std::string name = stream.readString();
-        unsigned int elementIndex = stream.readInt<unsigned int>();
-        unsigned int dataSize = stream.readInt<unsigned int>();
-
-        UniformBlock *uniformBlock = new UniformBlock(name, elementIndex, dataSize);
+    mProgram->save(&stream);
 
-        stream.readInt(&uniformBlock->psRegisterIndex);
-        stream.readInt(&uniformBlock->vsRegisterIndex);
+    GLsizei streamLength = stream.length();
+    const void *streamData = stream.data();
 
-        unsigned int numMembers = stream.readInt<unsigned int>();
-        uniformBlock->memberUniformIndexes.resize(numMembers);
-        for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
+    if (streamLength > bufSize)
+    {
+        if (length)
         {
-            stream.readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]);
+            *length = 0;
         }
 
-        mUniformBlocks[uniformBlockIndex] = uniformBlock;
-    }
-
-    const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
-    if (stream.error())
-    {
-        infoLog.append("Invalid program binary.");
-        return false;
+        // TODO: This should be moved to the validation layer but computing the size of the binary before saving
+        // it causes the save to happen twice.  It may be possible to write the binary to a separate buffer, validate
+        // sizes and then copy it.
+        return Error(GL_INVALID_OPERATION);
     }
 
-    mUniformIndex.resize(uniformIndexCount);
-    for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++)
+    if (binary)
     {
-        stream.readString(&mUniformIndex[uniformIndexIndex].name);
-        stream.readInt(&mUniformIndex[uniformIndexIndex].element);
-        stream.readInt(&mUniformIndex[uniformIndexIndex].index);
-    }
+        char *ptr = (char*) binary;
 
-    stream.readInt(&mTransformFeedbackBufferMode);
-    const unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
-    mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
-    for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
-    {
-        LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
+        memcpy(ptr, streamData, streamLength);
+        ptr += streamLength;
 
-        stream.readString(&varying.name);
-        stream.readInt(&varying.type);
-        stream.readInt(&varying.size);
-        stream.readString(&varying.semanticName);
-        stream.readInt(&varying.semanticIndex);
-        stream.readInt(&varying.semanticIndexCount);
+        ASSERT(ptr - streamLength == binary);
     }
 
-    const unsigned int vertexShaderCount = stream.readInt<unsigned int>();
-    for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
+    if (length)
     {
-        VertexFormat inputLayout[MAX_VERTEX_ATTRIBS];
-
-        for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++)
-        {
-            VertexFormat *vertexInput = &inputLayout[inputIndex];
-            stream.readInt(&vertexInput->mType);
-            stream.readInt(&vertexInput->mNormalized);
-            stream.readInt(&vertexInput->mComponents);
-            stream.readBool(&vertexInput->mPureInteger);
-        }
+        *length = streamLength;
+    }
 
-        unsigned int vertexShaderSize = stream.readInt<unsigned int>();
-        const unsigned char *vertexShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset();
-        rx::ShaderExecutable *shaderExecutable = mProgram->getRenderer()->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction),
-                                                                           vertexShaderSize, rx::SHADER_VERTEX,
-                                                                           mTransformFeedbackLinkedVaryings,
-                                                                           (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
-        if (!shaderExecutable)
-        {
-            infoLog.append("Could not create vertex shader.");
-            return false;
-        }
+    return Error(GL_NO_ERROR);
+}
 
-        // generated converted input layout
-        GLenum signature[MAX_VERTEX_ATTRIBS];
-        mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature);
+GLint ProgramBinary::getLength()
+{
+    GLint length;
+    Error error = save(NULL, NULL, INT_MAX, &length);
+    if (error.isError())
+    {
+        return 0;
+    }
 
-        // add new binary
-        mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
+    return length;
+}
 
-        stream.skip(vertexShaderSize);
+LinkResult ProgramBinary::link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings,
+                               Shader *fragmentShader, Shader *vertexShader,
+                               const std::vector<std::string> &transformFeedbackVaryings,
+                               GLenum transformFeedbackBufferMode)
+{
+    if (!fragmentShader || !fragmentShader->isCompiled())
+    {
+        return LinkResult(false, Error(GL_NO_ERROR));
     }
+    ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
 
-    const size_t pixelShaderCount = stream.readInt<unsigned int>();
-    for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
+    if (!vertexShader || !vertexShader->isCompiled())
     {
-        const size_t outputCount = stream.readInt<unsigned int>();
-        std::vector<GLenum> outputs(outputCount);
-        for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
-        {
-            stream.readInt(&outputs[outputIndex]);
-        }
-
-        const size_t pixelShaderSize = stream.readInt<unsigned int>();
-        const unsigned char *pixelShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset();
-        rx::Renderer *renderer = mProgram->getRenderer();
-        rx::ShaderExecutable *shaderExecutable = renderer->loadExecutable(pixelShaderFunction, pixelShaderSize,
-                                                                          rx::SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
-                                                                          (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
-
-        if (!shaderExecutable)
-        {
-            infoLog.append("Could not create pixel shader.");
-            return false;
-        }
-
-        // add new binary
-        mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
-
-        stream.skip(pixelShaderSize);
+        return LinkResult(false, Error(GL_NO_ERROR));
     }
+    ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
 
-    unsigned int geometryShaderSize = stream.readInt<unsigned int>();
+    reset();
 
-    if (geometryShaderSize > 0)
+    int registers;
+    std::vector<LinkedVarying> linkedVaryings;
+    LinkResult result = mProgram->link(data, infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode,
+                                       &registers, &linkedVaryings, &mOutputVariables);
+    if (result.error.isError() || !result.linkSuccess)
     {
-        const char *geometryShaderFunction = (const char*) binary + stream.offset();
-        rx::Renderer *renderer = mProgram->getRenderer();
-        mGeometryExecutable = renderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction),
-                                                       geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
-                                                       (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
-
-        if (!mGeometryExecutable)
-        {
-            infoLog.append("Could not create geometry shader.");
-            return false;
-        }
-        stream.skip(geometryShaderSize);
+        return result;
     }
 
-    if (!mProgram->load(infoLog, &stream))
+    if (!linkAttributes(infoLog, attributeBindings, vertexShader))
     {
-        return false;
+        return LinkResult(false, Error(GL_NO_ERROR));
     }
 
-    const char *ptr = (const char*) binary + stream.offset();
+    if (!mProgram->linkUniforms(infoLog, *vertexShader, *fragmentShader, *data.caps))
+    {
+        return LinkResult(false, Error(GL_NO_ERROR));
+    }
 
-    const GUID *binaryIdentifier = (const GUID *) ptr;
-    ptr += sizeof(GUID);
+    if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, *data.caps))
+    {
+        return LinkResult(false, Error(GL_NO_ERROR));
+    }
 
-    GUID identifier = mProgram->getRenderer()->getAdapterIdentifier();
-    if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0)
+    if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
+                                               transformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), *data.caps))
     {
-        infoLog.append("Invalid program binary.");
-        return false;
+        return LinkResult(false, Error(GL_NO_ERROR));
     }
 
-    mProgram->initializeUniformStorage(mUniforms);
+    // TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called,
+    // however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling.
+    result = mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers);
+    if (result.error.isError() || !result.linkSuccess)
+    {
+        infoLog.append("Failed to create D3D shaders.");
+        reset();
+        return result;
+    }
 
-    return true;
-#endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
+    return LinkResult(true, Error(GL_NO_ERROR));
 }
 
-bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length)
+bool ProgramBinary::linkUniformBlocks(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader,
+                                   const gl::Caps &caps)
 {
-    if (binaryFormat)
-    {
-        *binaryFormat = mProgram->getBinaryFormat();
-    }
+    const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks();
+    const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks();
 
-    BinaryOutputStream stream;
+    // Check that interface blocks defined in the vertex and fragment shaders are identical
+    typedef std::map<std::string, const sh::InterfaceBlock*> UniformBlockMap;
+    UniformBlockMap linkedUniformBlocks;
 
-    stream.writeInt(mProgram->getBinaryFormat());
-    stream.writeInt(ANGLE_MAJOR_VERSION);
-    stream.writeInt(ANGLE_MINOR_VERSION);
-    stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
-    stream.writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
-
-    for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
-    {
-        stream.writeInt(mLinkedAttribute[i].type);
-        stream.writeString(mLinkedAttribute[i].name);
-        stream.writeInt(mShaderAttributes[i].type);
-        stream.writeString(mShaderAttributes[i].name);
-        stream.writeInt(mSemanticIndex[i]);
-    }
-
-    stream.writeInt(mSamplersPS.size());
-    for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
-    {
-        stream.writeInt(mSamplersPS[i].active);
-        stream.writeInt(mSamplersPS[i].logicalTextureUnit);
-        stream.writeInt(mSamplersPS[i].textureType);
-    }
-
-    stream.writeInt(mSamplersVS.size());
-    for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
-    {
-        stream.writeInt(mSamplersVS[i].active);
-        stream.writeInt(mSamplersVS[i].logicalTextureUnit);
-        stream.writeInt(mSamplersVS[i].textureType);
-    }
-
-    stream.writeInt(mUsedVertexSamplerRange);
-    stream.writeInt(mUsedPixelSamplerRange);
-    stream.writeInt(mUsesPointSize);
-    stream.writeInt(mShaderVersion);
-
-    stream.writeInt(mUniforms.size());
-    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
-    {
-        const LinkedUniform &uniform = *mUniforms[uniformIndex];
-
-        stream.writeInt(uniform.type);
-        stream.writeInt(uniform.precision);
-        stream.writeString(uniform.name);
-        stream.writeInt(uniform.arraySize);
-        stream.writeInt(uniform.blockIndex);
-
-        stream.writeInt(uniform.blockInfo.offset);
-        stream.writeInt(uniform.blockInfo.arrayStride);
-        stream.writeInt(uniform.blockInfo.matrixStride);
-        stream.writeInt(uniform.blockInfo.isRowMajorMatrix);
-
-        stream.writeInt(uniform.psRegisterIndex);
-        stream.writeInt(uniform.vsRegisterIndex);
-        stream.writeInt(uniform.registerCount);
-        stream.writeInt(uniform.registerElement);
-    }
-
-    stream.writeInt(mUniformBlocks.size());
-    for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex)
-    {
-        const UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
-
-        stream.writeString(uniformBlock.name);
-        stream.writeInt(uniformBlock.elementIndex);
-        stream.writeInt(uniformBlock.dataSize);
-
-        stream.writeInt(uniformBlock.memberUniformIndexes.size());
-        for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
-        {
-            stream.writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]);
-        }
-
-        stream.writeInt(uniformBlock.psRegisterIndex);
-        stream.writeInt(uniformBlock.vsRegisterIndex);
-    }
-
-    stream.writeInt(mUniformIndex.size());
-    for (size_t i = 0; i < mUniformIndex.size(); ++i)
-    {
-        stream.writeString(mUniformIndex[i].name);
-        stream.writeInt(mUniformIndex[i].element);
-        stream.writeInt(mUniformIndex[i].index);
-    }
-
-    stream.writeInt(mTransformFeedbackBufferMode);
-    stream.writeInt(mTransformFeedbackLinkedVaryings.size());
-    for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
+    for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
     {
-        const LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
-
-        stream.writeString(varying.name);
-        stream.writeInt(varying.type);
-        stream.writeInt(varying.size);
-        stream.writeString(varying.semanticName);
-        stream.writeInt(varying.semanticIndex);
-        stream.writeInt(varying.semanticIndexCount);
+        const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex];
+        linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
     }
 
-    stream.writeInt(mVertexExecutables.size());
-    for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
+    for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
     {
-        VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
-
-        for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
+        const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex];
+        UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name);
+        if (entry != linkedUniformBlocks.end())
         {
-            const VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex];
-            stream.writeInt(vertexInput.mType);
-            stream.writeInt(vertexInput.mNormalized);
-            stream.writeInt(vertexInput.mComponents);
-            stream.writeInt(vertexInput.mPureInteger);
+            const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
+            if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock))
+            {
+                return false;
+            }
         }
-
-        size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
-        stream.writeInt(vertexShaderSize);
-
-        const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
-        stream.writeBytes(vertexBlob, vertexShaderSize);
     }
 
-    stream.writeInt(mPixelExecutables.size());
-    for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
+    for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
     {
-        PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
+        const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex];
 
-        const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
-        stream.writeInt(outputs.size());
-        for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
+        // Note: shared and std140 layouts are always considered active
+        if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
         {
-            stream.writeInt(outputs[outputIndex]);
+            if (!mProgram->defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps))
+            {
+                return false;
+            }
         }
-
-        size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
-        stream.writeInt(pixelShaderSize);
-
-        const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
-        stream.writeBytes(pixelBlob, pixelShaderSize);
-    }
-
-    size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
-    stream.writeInt(geometryShaderSize);
-
-    if (mGeometryExecutable != NULL && geometryShaderSize > 0)
-    {
-        const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
-        stream.writeBytes(geometryBlob, geometryShaderSize);
     }
 
-    if (!mProgram->save(&stream))
+    for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
     {
-        if (length)
-        {
-            *length = 0;
-        }
-
-        return false;
-    }
-
-    GUID identifier = mProgram->getRenderer()->getAdapterIdentifier();
-
-    GLsizei streamLength = stream.length();
-    const void *streamData = stream.data();
+        const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex];
 
-    GLsizei totalLength = streamLength + sizeof(GUID);
-    if (totalLength > bufSize)
-    {
-        if (length)
+        // Note: shared and std140 layouts are always considered active
+        if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
         {
-            *length = 0;
+            if (!mProgram->defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps))
+            {
+                return false;
+            }
         }
-
-        return false;
-    }
-
-    if (binary)
-    {
-        char *ptr = (char*) binary;
-
-        memcpy(ptr, streamData, streamLength);
-        ptr += streamLength;
-
-        memcpy(ptr, &identifier, sizeof(GUID));
-        ptr += sizeof(GUID);
-
-        ASSERT(ptr - totalLength == binary);
-    }
-
-    if (length)
-    {
-        *length = totalLength;
     }
 
     return true;
 }
 
-GLint ProgramBinary::getLength()
+bool ProgramBinary::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
+                                            const sh::InterfaceBlock &fragmentInterfaceBlock)
 {
-    GLint length;
-    if (save(NULL, NULL, INT_MAX, &length))
-    {
-        return length;
-    }
-    else
-    {
-        return 0;
-    }
-}
+    const char* blockName = vertexInterfaceBlock.name.c_str();
 
-bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
-                         const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps)
-{
-    if (!fragmentShader || !fragmentShader->isCompiled())
+    // validate blocks for the same member types
+    if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size())
     {
+        infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName);
         return false;
     }
-    ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
 
-    if (!vertexShader || !vertexShader->isCompiled())
+    if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize)
     {
+        infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName);
         return false;
     }
-    ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
-
-    reset();
-
-    mSamplersPS.resize(caps.maxTextureImageUnits);
-    mSamplersVS.resize(caps.maxVertexTextureImageUnits);
 
-    mTransformFeedbackBufferMode = transformFeedbackBufferMode;
-
-    rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
-    rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
-
-    mShaderVersion = vertexShaderD3D->getShaderVersion();
-
-    int registers;
-    std::vector<LinkedVarying> linkedVaryings;
-    if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, &registers, &linkedVaryings, &mOutputVariables))
+    if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
     {
+        infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName);
         return false;
     }
 
-    mUsesPointSize = vertexShaderD3D->usesPointSize();
-
-    bool success = true;
-
-    if (!linkAttributes(infoLog, attributeBindings, vertexShader))
-    {
-        success = false;
-    }
-
-    if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps))
-    {
-        success = false;
-    }
-
-    // special case for gl_DepthRange, the only built-in uniform (also a struct)
-    if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange())
-    {
-        const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo();
-
-        mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo));
-        mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo));
-        mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo));
-    }
-
-    if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps))
-    {
-        success = false;
-    }
-
-    if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
-                                               transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings, caps))
-    {
-        success = false;
-    }
-
-    if (success)
+    const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size();
+    for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
     {
-        VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS];
-        GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout);
-        rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout);
-
-        std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(mProgram->getPixelShaderKey());
-        rx::ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput);
+        const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex];
+        const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex];
 
-        if (usesGeometryShader())
+        if (vertexMember.name != fragmentMember.name)
         {
-            std::string geometryHLSL = mProgram->getDynamicHLSL()->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
-            mGeometryExecutable = mProgram->getRenderer()->compileToExecutable(infoLog, geometryHLSL.c_str(),
-                                                                               rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
-                                                                               (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
-                                                                               rx::ANGLE_D3D_WORKAROUND_NONE);
+            infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')",
+                           blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str());
+            return false;
         }
 
-        if (!defaultVertexExecutable || !defaultPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
+        std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
+        if (!gl::ProgramBinary::linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember))
         {
-            infoLog.append("Failed to create D3D shaders.");
-            success = false;
-            reset();
+            return false;
         }
     }
 
-    return success;
+    return true;
 }
 
 // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
@@ -1688,7 +682,7 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at
 
         const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
 
-        mShaderAttributes[attributeIndex] = attribute;
+        mProgram->getShaderAttributes()[attributeIndex] = attribute;
 
         if (location != -1)   // Set by glBindAttribLocation or by location layout qualifier
         {
@@ -1708,7 +702,7 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at
 
                 // In GLSL 3.00, attribute aliasing produces a link error
                 // In GLSL 1.00, attribute aliasing is allowed
-                if (mShaderVersion >= 300)
+                if (mProgram->getShaderVersion() >= 300)
                 {
                     if (!linkedAttribute.name.empty())
                     {
@@ -1739,395 +733,73 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at
 
             if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
             {
-                infoLog.append("Too many active attributes (%s)", attribute.name.c_str());
-
-                return false;   // Fail to link
-            }
-
-            mLinkedAttribute[availableIndex] = attribute;
-        }
-    }
-
-    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
-    {
-        int index = vertexShaderD3D->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
-        int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type);
-
-        for (int r = 0; r < rows; r++)
-        {
-            mSemanticIndex[attributeIndex++] = index++;
-        }
-    }
-
-    initAttributesByLayout();
-
-    return true;
-}
-
-bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable,
-                                              const sh::ShaderVariable &fragmentVariable, bool validatePrecision)
-{
-    if (vertexVariable.type != fragmentVariable.type)
-    {
-        infoLog.append("Types for %s differ between vertex and fragment shaders", variableName.c_str());
-        return false;
-    }
-    if (vertexVariable.arraySize != fragmentVariable.arraySize)
-    {
-        infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str());
-        return false;
-    }
-    if (validatePrecision && vertexVariable.precision != fragmentVariable.precision)
-    {
-        infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str());
-        return false;
-    }
-
-    if (vertexVariable.fields.size() != fragmentVariable.fields.size())
-    {
-        infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", variableName.c_str());
-        return false;
-    }
-    const unsigned int numMembers = vertexVariable.fields.size();
-    for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
-    {
-        const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex];
-        const sh::ShaderVariable &fragmentMember = fragmentVariable.fields[memberIndex];
-
-        if (vertexMember.name != fragmentMember.name)
-        {
-            infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')",
-                           memberIndex, variableName.c_str(),
-                           vertexMember.name.c_str(), fragmentMember.name.c_str());
-            return false;
-        }
-
-        const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." +
-                                       vertexMember.name + "'";
-
-        if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision))
-        {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform)
-{
-    if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
-    {
-        return false;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying)
-{
-    if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
-    {
-        return false;
-    }
-
-    if (vertexVarying.interpolation != fragmentVarying.interpolation)
-    {
-        infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str());
-        return false;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
-{
-    if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
-    {
-        return false;
-    }
-
-    if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout)
-    {
-        infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str());
-        return false;
-    }
-
-    return true;
-}
-
-bool ProgramBinary::linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps)
-{
-    const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader.getImplementation());
-    const rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader.getImplementation());
-
-    const std::vector<sh::Uniform> &vertexUniforms = vertexShader.getUniforms();
-    const std::vector<sh::Uniform> &fragmentUniforms = fragmentShader.getUniforms();
-
-    // Check that uniforms defined in the vertex and fragment shaders are identical
-    typedef std::map<std::string, const sh::Uniform*> UniformMap;
-    UniformMap linkedUniforms;
-
-    for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++)
-    {
-        const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex];
-        linkedUniforms[vertexUniform.name] = &vertexUniform;
-    }
-
-    for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++)
-    {
-        const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex];
-        UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name);
-        if (entry != linkedUniforms.end())
-        {
-            const sh::Uniform &vertexUniform = *entry->second;
-            const std::string &uniformName = "uniform '" + vertexUniform.name + "'";
-            if (!linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform))
-            {
-                return false;
-            }
-        }
-    }
-
-    for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++)
-    {
-        const sh::Uniform &uniform = vertexUniforms[uniformIndex];
-
-        if (uniform.staticUse)
-        {
-            defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name));
-        }
-    }
-
-    for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++)
-    {
-        const sh::Uniform &uniform = fragmentUniforms[uniformIndex];
-
-        if (uniform.staticUse)
-        {
-            defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name));
-        }
-    }
-
-    if (!indexUniforms(infoLog, caps))
-    {
-        return false;
-    }
-
-    mProgram->initializeUniformStorage(mUniforms);
-
-    return true;
-}
-
-void ProgramBinary::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister)
-{
-    ShShaderOutput outputType = rx::ShaderD3D::getCompilerOutputType(shader);
-    sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
-    encoder.skipRegisters(uniformRegister);
-
-    defineUniform(shader, uniform, uniform.name, &encoder);
-}
-
-void ProgramBinary::defineUniform(GLenum shader, const sh::ShaderVariable &uniform,
-                                  const std::string &fullName, sh::HLSLBlockEncoder *encoder)
-{
-    if (uniform.isStruct())
-    {
-        for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
-        {
-            const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
-
-            encoder->enterAggregateType();
-
-            for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
-            {
-                const sh::ShaderVariable &field = uniform.fields[fieldIndex];
-                const std::string &fieldFullName = (fullName + elementString + "." + field.name);
-
-                defineUniform(shader, field, fieldFullName, encoder);
-            }
-
-            encoder->exitAggregateType();
-        }
-    }
-    else // Not a struct
-    {
-        // Arrays are treated as aggregate types
-        if (uniform.isArray())
-        {
-            encoder->enterAggregateType();
-        }
-
-        LinkedUniform *linkedUniform = getUniformByName(fullName);
-
-        if (!linkedUniform)
-        {
-            linkedUniform = new LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
-                                              -1, sh::BlockMemberInfo::getDefaultBlockInfo());
-            ASSERT(linkedUniform);
-            linkedUniform->registerElement = encoder->getCurrentElement();
-            mUniforms.push_back(linkedUniform);
-        }
-
-        ASSERT(linkedUniform->registerElement == encoder->getCurrentElement());
-
-        if (shader == GL_FRAGMENT_SHADER)
-        {
-            linkedUniform->psRegisterIndex = encoder->getCurrentRegister();
-        }
-        else if (shader == GL_VERTEX_SHADER)
-        {
-            linkedUniform->vsRegisterIndex = encoder->getCurrentRegister();
-        }
-        else UNREACHABLE();
-
-        // Advance the uniform offset, to track registers allocation for structs
-        encoder->encodeType(uniform.type, uniform.arraySize, false);
-
-        // Arrays are treated as aggregate types
-        if (uniform.isArray())
-        {
-            encoder->exitAggregateType();
-        }
-    }
-}
-
-bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps)
-{
-    ASSERT(IsSampler(uniform.type));
-    ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX);
-
-    if (uniform.vsRegisterIndex != GL_INVALID_INDEX)
-    {
-        if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS,
-                            &mUsedVertexSamplerRange))
-        {
-            infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).",
-                           mSamplersVS.size());
-            return false;
-        }
-
-        unsigned int maxVertexVectors = mProgram->getRenderer()->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors;
-        if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors)
-        {
-            infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)",
-                           caps.maxVertexUniformVectors);
-            return false;
-        }
-    }
-
-    if (uniform.psRegisterIndex != GL_INVALID_INDEX)
-    {
-        if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS,
-                            &mUsedPixelSamplerRange))
-        {
-            infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).",
-                           mSamplersPS.size());
-            return false;
-        }
-
-        unsigned int maxFragmentVectors = mProgram->getRenderer()->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors;
-        if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors)
-        {
-            infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)",
-                           caps.maxFragmentUniformVectors);
-            return false;
-        }
-    }
-
-    return true;
-}
-
-bool ProgramBinary::indexUniforms(InfoLog &infoLog, const Caps &caps)
-{
-    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
-    {
-        const LinkedUniform &uniform = *mUniforms[uniformIndex];
-
-        if (IsSampler(uniform.type))
-        {
-            if (!indexSamplerUniform(uniform, infoLog, caps))
-            {
-                return false;
+                infoLog.append("Too many active attributes (%s)", attribute.name.c_str());
+
+                return false;   // Fail to link
             }
-        }
 
-        for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++)
-        {
-            mUniformIndex.push_back(VariableLocation(uniform.name, arrayElementIndex, uniformIndex));
+            mLinkedAttribute[availableIndex] = attribute;
         }
     }
 
-    return true;
-}
-
-bool ProgramBinary::assignSamplers(unsigned int startSamplerIndex,
-                                   GLenum samplerType,
-                                   unsigned int samplerCount,
-                                   std::vector<Sampler> &outSamplers,
-                                   GLuint *outUsedRange)
-{
-    unsigned int samplerIndex = startSamplerIndex;
-
-    do
+    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
     {
-        if (samplerIndex < outSamplers.size())
-        {
-            Sampler& sampler = outSamplers[samplerIndex];
-            sampler.active = true;
-            sampler.textureType = GetTextureType(samplerType);
-            sampler.logicalTextureUnit = 0;
-            *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
-        }
-        else
+        int index = vertexShaderD3D->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
+        int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type);
+
+        for (int r = 0; r < rows; r++)
         {
-            return false;
+            mSemanticIndex[attributeIndex++] = index++;
         }
+    }
 
-        samplerIndex++;
-    } while (samplerIndex < startSamplerIndex + samplerCount);
+    initAttributesByLayout();
 
     return true;
 }
 
-bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock)
+bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable,
+                                              const sh::ShaderVariable &fragmentVariable, bool validatePrecision)
 {
-    const char* blockName = vertexInterfaceBlock.name.c_str();
-
-    // validate blocks for the same member types
-    if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size())
+    if (vertexVariable.type != fragmentVariable.type)
     {
-        infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName);
+        infoLog.append("Types for %s differ between vertex and fragment shaders", variableName.c_str());
         return false;
     }
-
-    if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize)
+    if (vertexVariable.arraySize != fragmentVariable.arraySize)
     {
-        infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName);
+        infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str());
         return false;
     }
-
-    if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
+    if (validatePrecision && vertexVariable.precision != fragmentVariable.precision)
     {
-        infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName);
+        infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str());
         return false;
     }
 
-    const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size();
-    for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
+    if (vertexVariable.fields.size() != fragmentVariable.fields.size())
     {
-        const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex];
-        const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex];
+        infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", variableName.c_str());
+        return false;
+    }
+    const unsigned int numMembers = vertexVariable.fields.size();
+    for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
+    {
+        const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex];
+        const sh::ShaderVariable &fragmentMember = fragmentVariable.fields[memberIndex];
 
         if (vertexMember.name != fragmentMember.name)
         {
-            infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')",
-                           blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str());
+            infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')",
+                           memberIndex, variableName.c_str(),
+                           vertexMember.name.c_str(), fragmentMember.name.c_str());
             return false;
         }
 
-        std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
-        if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember))
+        const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." +
+                                       vertexMember.name + "'";
+
+        if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision))
         {
             return false;
         }
@@ -2136,61 +808,43 @@ bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::Inter
     return true;
 }
 
-bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps)
+bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform)
 {
-    const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks();
-    const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks();
+    if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
+    {
+        return false;
+    }
 
-    // Check that interface blocks defined in the vertex and fragment shaders are identical
-    typedef std::map<std::string, const sh::InterfaceBlock*> UniformBlockMap;
-    UniformBlockMap linkedUniformBlocks;
+    return true;
+}
 
-    for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
+bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying)
+{
+    if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
     {
-        const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex];
-        linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
+        return false;
     }
 
-    for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
+    if (vertexVarying.interpolation != fragmentVarying.interpolation)
     {
-        const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex];
-        UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name);
-        if (entry != linkedUniformBlocks.end())
-        {
-            const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
-            if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock))
-            {
-                return false;
-            }
-        }
+        infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str());
+        return false;
     }
 
-    for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
-    {
-        const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex];
+    return true;
+}
 
-        // Note: shared and std140 layouts are always considered active
-        if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
-        {
-            if (!defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps))
-            {
-                return false;
-            }
-        }
+bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
+{
+    if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
+    {
+        return false;
     }
 
-    for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
+    if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout)
     {
-        const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex];
-
-        // Note: shared and std140 layouts are always considered active
-        if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
-        {
-            if (!defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps))
-            {
-                return false;
-            }
-        }
+        infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str());
+        return false;
     }
 
     return true;
@@ -2253,142 +907,6 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons
     return true;
 }
 
-template <typename VarT>
-void ProgramBinary::defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
-                                              sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
-                                              bool inRowMajorLayout)
-{
-    for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++)
-    {
-        const VarT &field = fields[uniformIndex];
-        const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
-
-        if (field.isStruct())
-        {
-            bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
-
-            for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
-            {
-                encoder->enterAggregateType();
-
-                const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
-                defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout);
-
-                encoder->exitAggregateType();
-            }
-        }
-        else
-        {
-            bool isRowMajorMatrix = (IsMatrixType(field.type) && inRowMajorLayout);
-
-            sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
-
-            LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize,
-                                                          blockIndex, memberInfo);
-
-            // add to uniform list, but not index, since uniform block uniforms have no location
-            blockUniformIndexes->push_back(mUniforms.size());
-            mUniforms.push_back(newUniform);
-        }
-    }
-}
-
-bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps)
-{
-    const rx::ShaderD3D* shaderD3D = rx::ShaderD3D::makeShaderD3D(shader.getImplementation());
-
-    // create uniform block entries if they do not exist
-    if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX)
-    {
-        std::vector<unsigned int> blockUniformIndexes;
-        const unsigned int blockIndex = mUniformBlocks.size();
-
-        // define member uniforms
-        sh::BlockLayoutEncoder *encoder = NULL;
-
-        if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
-        {
-            encoder = new sh::Std140BlockEncoder;
-        }
-        else
-        {
-            encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
-        }
-        ASSERT(encoder);
-
-        defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout);
-
-        size_t dataSize = encoder->getBlockSize();
-
-        // create all the uniform blocks
-        if (interfaceBlock.arraySize > 0)
-        {
-            for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++)
-            {
-                UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize);
-                newUniformBlock->memberUniformIndexes = blockUniformIndexes;
-                mUniformBlocks.push_back(newUniformBlock);
-            }
-        }
-        else
-        {
-            UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize);
-            newUniformBlock->memberUniformIndexes = blockUniformIndexes;
-            mUniformBlocks.push_back(newUniformBlock);
-        }
-    }
-
-    if (interfaceBlock.staticUse)
-    {
-        // Assign registers to the uniform blocks
-        const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name);
-        const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize);
-        ASSERT(blockIndex != GL_INVALID_INDEX);
-        ASSERT(blockIndex + elementCount <= mUniformBlocks.size());
-
-        unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name);
-
-        for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++)
-        {
-            UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement];
-            ASSERT(uniformBlock->name == interfaceBlock.name);
-
-            if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(),
-                                            interfaceBlockRegister + uniformBlockElement, caps))
-            {
-                return false;
-            }
-        }
-    }
-
-    return true;
-}
-
-bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps)
-{
-    if (shader == GL_VERTEX_SHADER)
-    {
-        uniformBlock->vsRegisterIndex = registerIndex;
-        if (registerIndex - mProgram->getRenderer()->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks)
-        {
-            infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks);
-            return false;
-        }
-    }
-    else if (shader == GL_FRAGMENT_SHADER)
-    {
-        uniformBlock->psRegisterIndex = registerIndex;
-        if (registerIndex - mProgram->getRenderer()->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks)
-        {
-            infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks);
-            return false;
-        }
-    }
-    else UNREACHABLE();
-
-    return true;
-}
-
 bool ProgramBinary::isValidated() const
 {
     return mValidated;
@@ -2464,13 +982,13 @@ GLint ProgramBinary::getActiveAttributeMaxLength() const
 
 void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
 {
-    ASSERT(index < mUniforms.size());   // index must be smaller than getActiveUniformCount()
+    ASSERT(index < mProgram->getUniforms().size());   // index must be smaller than getActiveUniformCount()
 
     if (bufsize > 0)
     {
-        std::string string = mUniforms[index]->name;
+        std::string string = mProgram->getUniforms()[index]->name;
 
-        if (mUniforms[index]->isArray())
+        if (mProgram->getUniforms()[index]->isArray())
         {
             string += "[0]";
         }
@@ -2484,27 +1002,27 @@ void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *len
         }
     }
 
-    *size = mUniforms[index]->elementCount();
+    *size = mProgram->getUniforms()[index]->elementCount();
 
-    *type = mUniforms[index]->type;
+    *type = mProgram->getUniforms()[index]->type;
 }
 
 GLint ProgramBinary::getActiveUniformCount() const
 {
-    return mUniforms.size();
+    return mProgram->getUniforms().size();
 }
 
 GLint ProgramBinary::getActiveUniformMaxLength() const
 {
     int maxLength = 0;
 
-    unsigned int numUniforms = mUniforms.size();
+    unsigned int numUniforms = mProgram->getUniforms().size();
     for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
     {
-        if (!mUniforms[uniformIndex]->name.empty())
+        if (!mProgram->getUniforms()[uniformIndex]->name.empty())
         {
-            int length = (int)(mUniforms[uniformIndex]->name.length() + 1);
-            if (mUniforms[uniformIndex]->isArray())
+            int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1);
+            if (mProgram->getUniforms()[uniformIndex]->isArray())
             {
                 length += 3;  // Counting in "[0]".
             }
@@ -2517,7 +1035,7 @@ GLint ProgramBinary::getActiveUniformMaxLength() const
 
 GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const
 {
-    const gl::LinkedUniform& uniform = *mUniforms[index];
+    const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index];
 
     switch (pname)
     {
@@ -2540,34 +1058,25 @@ GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const
 
 bool ProgramBinary::isValidUniformLocation(GLint location) const
 {
-    ASSERT(rx::IsIntegerCastSafe<GLint>(mUniformIndex.size()));
-    return (location >= 0 && location < static_cast<GLint>(mUniformIndex.size()));
+    ASSERT(rx::IsIntegerCastSafe<GLint>(mProgram->getUniformIndices().size()));
+    return (location >= 0 && location < static_cast<GLint>(mProgram->getUniformIndices().size()));
 }
 
 LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const
 {
-    ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformIndex.size());
-    return mUniforms[mUniformIndex[location].index];
+    return mProgram->getUniformByLocation(location);
 }
 
 LinkedUniform *ProgramBinary::getUniformByName(const std::string &name) const
 {
-    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
-    {
-        if (mUniforms[uniformIndex]->name == name)
-        {
-            return mUniforms[uniformIndex];
-        }
-    }
-
-    return NULL;
+    return mProgram->getUniformByName(name);
 }
 
 void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
 {
-    ASSERT(uniformBlockIndex < mUniformBlocks.size());   // index must be smaller than getActiveUniformBlockCount()
+    ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size());   // index must be smaller than getActiveUniformBlockCount()
 
-    const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
+    const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
 
     if (bufSize > 0)
     {
@@ -2590,9 +1099,9 @@ void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei
 
 void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
 {
-    ASSERT(uniformBlockIndex < mUniformBlocks.size());   // index must be smaller than getActiveUniformBlockCount()
+    ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size());   // index must be smaller than getActiveUniformBlockCount()
 
-    const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
+    const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
 
     switch (pname)
     {
@@ -2625,17 +1134,17 @@ void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pna
 
 GLuint ProgramBinary::getActiveUniformBlockCount() const
 {
-    return mUniformBlocks.size();
+    return mProgram->getUniformBlocks().size();
 }
 
 GLuint ProgramBinary::getActiveUniformBlockMaxLength() const
 {
     unsigned int maxLength = 0;
 
-    unsigned int numUniformBlocks = mUniformBlocks.size();
+    unsigned int numUniformBlocks = mProgram->getUniformBlocks().size();
     for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
     {
-        const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
+        const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
         if (!uniformBlock.name.empty())
         {
             const unsigned int length = uniformBlock.name.length() + 1;
@@ -2665,88 +1174,7 @@ void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps)
 
 bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps)
 {
-    // if any two active samplers in a program are of different types, but refer to the same
-    // texture image unit, and this is the current program, then ValidateProgram will fail, and
-    // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
-    updateSamplerMapping();
-
-    std::vector<GLenum> textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE);
-
-    for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
-    {
-        if (mSamplersPS[i].active)
-        {
-            unsigned int unit = mSamplersPS[i].logicalTextureUnit;
-
-            if (unit >= textureUnitTypes.size())
-            {
-                if (infoLog)
-                {
-                    infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size());
-                }
-
-                return false;
-            }
-
-            if (textureUnitTypes[unit] != GL_NONE)
-            {
-                if (mSamplersPS[i].textureType != textureUnitTypes[unit])
-                {
-                    if (infoLog)
-                    {
-                        infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
-                    }
-
-                    return false;
-                }
-            }
-            else
-            {
-                textureUnitTypes[unit] = mSamplersPS[i].textureType;
-            }
-        }
-    }
-
-    for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
-    {
-        if (mSamplersVS[i].active)
-        {
-            unsigned int unit = mSamplersVS[i].logicalTextureUnit;
-
-            if (unit >= textureUnitTypes.size())
-            {
-                if (infoLog)
-                {
-                    infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size());
-                }
-
-                return false;
-            }
-
-            if (textureUnitTypes[unit] != GL_NONE)
-            {
-                if (mSamplersVS[i].textureType != textureUnitTypes[unit])
-                {
-                    if (infoLog)
-                    {
-                        infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
-                    }
-
-                    return false;
-                }
-            }
-            else
-            {
-                textureUnitTypes[unit] = mSamplersVS[i].textureType;
-            }
-        }
-    }
-
-    return true;
-}
-
-ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
-{
+    return mProgram->validateSamplers(infoLog, caps);
 }
 
 struct AttributeSorter
@@ -2795,26 +1223,6 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA
 
 void ProgramBinary::reset()
 {
-    SafeDeleteContainer(mVertexExecutables);
-    SafeDeleteContainer(mPixelExecutables);
-
-    SafeDelete(mGeometryExecutable);
-
-    mTransformFeedbackBufferMode = GL_NONE;
-    mTransformFeedbackLinkedVaryings.clear();
-
-    mSamplersPS.clear();
-    mSamplersVS.clear();
-
-    mUsedVertexSamplerRange = 0;
-    mUsedPixelSamplerRange = 0;
-    mUsesPointSize = false;
-    mShaderVersion = 0;
-    mDirtySamplerMapping = true;
-
-    SafeDeleteContainer(mUniforms);
-    SafeDeleteContainer(mUniformBlocks);
-    mUniformIndex.clear();
     mOutputVariables.clear();
 
     mProgram->reset();
diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h
index ad470d417b6..3142d66c6df 100644
--- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h
+++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h
@@ -24,11 +24,6 @@
 #include <string>
 #include <vector>
 
-// TODO(jmadill): place this in workarounds library
-#define ANGLE_WORKAROUND_ENABLED 1
-#define ANGLE_WORKAROUND_DISABLED 2
-#define ANGLE_MRT_PERF_WORKAROUND ANGLE_WORKAROUND_ENABLED
-
 namespace sh
 {
 class HLSLBlockEncoder;
@@ -44,7 +39,6 @@ class HLSLBlockEncoder;
 namespace rx
 {
 class ShaderExecutable;
-class Renderer;
 struct TranslatedAttribute;
 class UniformStorage;
 class ProgramImpl;
@@ -58,6 +52,7 @@ class InfoLog;
 class AttributeBindings;
 class Buffer;
 class Framebuffer;
+struct Data;
 
 // Struct used for correlating uniforms/elements of uniform arrays to handles
 struct VariableLocation
@@ -91,6 +86,14 @@ struct LinkedVarying
     unsigned int semanticIndexCount;
 };
 
+struct LinkResult
+{
+    bool linkSuccess;
+    Error error;
+
+    LinkResult(bool linkSuccess, const Error &error);
+};
+
 // This is the result of linking a program. It is the state that would be passed to ProgramBinary.
 class ProgramBinary : public RefCountObject
 {
@@ -101,11 +104,6 @@ class ProgramBinary : public RefCountObject
     rx::ProgramImpl *getImplementation() { return mProgram; }
     const rx::ProgramImpl *getImplementation() const { return mProgram; }
 
-    rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo);
-    rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout);
-    rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]);
-    rx::ShaderExecutable *getGeometryExecutable() const;
-
     GLuint getAttributeLocation(const char *name);
     int getSemanticIndex(int attributeIndex);
 
@@ -113,8 +111,6 @@ class ProgramBinary : public RefCountObject
     GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex);
     GLint getUsedSamplerRange(SamplerType type);
     bool usesPointSize() const;
-    bool usesPointSpriteEmulation() const;
-    bool usesGeometryShader() const;
 
     GLint getUniformLocation(std::string name);
     GLuint getUniformIndex(std::string name);
@@ -145,18 +141,17 @@ class ProgramBinary : public RefCountObject
     void getUniformiv(GLint location, GLint *params);
     void getUniformuiv(GLint location, GLuint *params);
 
-    void dirtyAllUniforms();
-
     Error applyUniforms();
     Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps);
 
-    bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
-    bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
+    LinkResult load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
+    Error save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
     GLint getLength();
 
-    bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
-              const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps);
-    void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
+    LinkResult link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings,
+                    Shader *fragmentShader, Shader *vertexShader,
+                    const std::vector<std::string> &transformFeedbackVaryings,
+                    GLenum transformFeedbackBufferMode);
 
     void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
     GLint getActiveAttributeCount() const;
@@ -188,30 +183,23 @@ class ProgramBinary : public RefCountObject
     void updateSamplerMapping();
 
     unsigned int getSerial() const;
-    int getShaderVersion() const;
 
     void initAttributesByLayout();
     void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const;
 
-    const std::vector<LinkedUniform*> &getUniforms() const { return mUniforms; }
-
     static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader);
+    static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
+    static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
 
-    struct Sampler
-    {
-        Sampler();
-
-        bool active;
-        GLint logicalTextureUnit;
-        GLenum textureType;
-    };
-
     void reset();
 
     bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader);
+    bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
+    bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
+                                    const sh::InterfaceBlock &fragmentInterfaceBlock);
 
     static bool linkValidateVariablesBase(InfoLog &infoLog,
                                           const std::string &variableName,
@@ -219,102 +207,21 @@ class ProgramBinary : public RefCountObject
                                           const sh::ShaderVariable &fragmentVariable,
                                           bool validatePrecision);
 
-    static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
     static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
-    static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
-    bool linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
-    void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister);
-    void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder);
-    bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps);
-    bool indexUniforms(InfoLog &infoLog, const Caps &caps);
-    static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount,
-                               std::vector<Sampler> &outSamplers, GLuint *outUsedRange);
-    bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock);
-    bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
     bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
                                                const std::vector<std::string> &transformFeedbackVaryingNames,
                                                GLenum transformFeedbackBufferMode,
                                                std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings,
                                                const Caps &caps) const;
-    template <typename VarT>
-    void defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
-                                   sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
-                                   bool inRowMajorLayout);
-    bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps);
     bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps);
     void defineOutputVariables(Shader *fragmentShader);
 
-    template <typename T>
-    void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType);
-
-    template <int cols, int rows>
-    void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType);
-
-    template <typename T>
-    void getUniformv(GLint location, T *params, GLenum uniformType);
-
-    class VertexExecutable
-    {
-      public:
-        VertexExecutable(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS],
-                         const GLenum signature[MAX_VERTEX_ATTRIBS],
-                         rx::ShaderExecutable *shaderExecutable);
-        ~VertexExecutable();
-
-        bool matchesSignature(const GLenum convertedLayout[MAX_VERTEX_ATTRIBS]) const;
-
-        const VertexFormat *inputs() const { return mInputs; }
-        const GLenum *signature() const { return mSignature; }
-        rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
-
-      private:
-        VertexFormat mInputs[MAX_VERTEX_ATTRIBS];
-        GLenum mSignature[MAX_VERTEX_ATTRIBS];
-        rx::ShaderExecutable *mShaderExecutable;
-    };
-
-    class PixelExecutable
-    {
-      public:
-        PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable);
-        ~PixelExecutable();
-
-        bool matchesSignature(const std::vector<GLenum> &signature) const { return mOutputSignature == signature; }
-
-        const std::vector<GLenum> &outputSignature() const { return mOutputSignature; }
-        rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
-
-      private:
-        std::vector<GLenum> mOutputSignature;
-        rx::ShaderExecutable *mShaderExecutable;
-    };
-
     rx::ProgramImpl *mProgram;
 
-    std::vector<VertexExecutable *> mVertexExecutables;
-    std::vector<PixelExecutable *> mPixelExecutables;
-
-    rx::ShaderExecutable *mGeometryExecutable;
-
     sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
-    sh::Attribute mShaderAttributes[MAX_VERTEX_ATTRIBS];
     int mSemanticIndex[MAX_VERTEX_ATTRIBS];
     int mAttributesByLayout[MAX_VERTEX_ATTRIBS];
 
-    GLenum mTransformFeedbackBufferMode;
-    std::vector<LinkedVarying> mTransformFeedbackLinkedVaryings;
-
-    std::vector<Sampler> mSamplersPS;
-    std::vector<Sampler> mSamplersVS;
-    GLuint mUsedVertexSamplerRange;
-    GLuint mUsedPixelSamplerRange;
-    bool mUsesPointSize;
-    int mShaderVersion;
-    bool mDirtySamplerMapping;
-
-    std::vector<LinkedUniform*> mUniforms;
-    std::vector<UniformBlock*> mUniformBlocks;
-    std::vector<VariableLocation> mUniformIndex;
     std::map<int, VariableLocation> mOutputVariables;
 
     bool mValidated;
diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp
index 9406fce58df..911a389dfa9 100644
--- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp
@@ -4,77 +4,86 @@
 // found in the LICENSE file.
 //
 
-// Renderbuffer.cpp: the gl::Renderbuffer class and its derived classes
-// Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer
-// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
+// Renderbuffer.cpp: Implements the renderer-agnostic gl::Renderbuffer class,
+// GL renderbuffer objects and related functionality.
+// [OpenGL ES 2.0.24] section 4.4.3 page 108.
 
 #include "libGLESv2/Renderbuffer.h"
 #include "libGLESv2/Texture.h"
 #include "libGLESv2/formatutils.h"
 #include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
 #include "libGLESv2/renderer/RenderTarget.h"
+#include "libGLESv2/renderer/RenderbufferImpl.h"
 
 #include "common/utilities.h"
 
 namespace gl
 {
-unsigned int RenderbufferStorage::mCurrentSerial = 1;
-
-Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *newStorage)
+Renderbuffer::Renderbuffer(rx::RenderbufferImpl *impl, GLuint id)
   : RefCountObject(id),
-    mStorage(newStorage)
+    mRenderbuffer(impl)
 {
-    ASSERT(mStorage);
+    ASSERT(mRenderbuffer);
+
+    mWidth = mRenderbuffer->getWidth();
+    mHeight = mRenderbuffer->getHeight();
+    mInternalFormat = mRenderbuffer->getInternalFormat();
+    mActualFormat = mRenderbuffer->getActualFormat();
+    mSamples = mRenderbuffer->getSamples();
 }
 
 Renderbuffer::~Renderbuffer()
 {
-    SafeDelete(mStorage);
+    SafeDelete(mRenderbuffer);
 }
 
-void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
+Error Renderbuffer::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
 {
-    ASSERT(newStorage);
+    Error error = mRenderbuffer->setStorage(width, height, internalformat, samples);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    SafeDelete(mStorage);
-    mStorage = newStorage;
+    mWidth = width;
+    mHeight = height;
+    mInternalFormat = internalformat;
+    mSamples = samples;
+    mActualFormat = mRenderbuffer->getActualFormat();
+
+    return Error(GL_NO_ERROR);
 }
 
-RenderbufferStorage *Renderbuffer::getStorage()
+rx::RenderbufferImpl *Renderbuffer::getImplementation()
 {
-    ASSERT(mStorage);
-    return mStorage;
+    ASSERT(mRenderbuffer);
+    return mRenderbuffer;
 }
 
 GLsizei Renderbuffer::getWidth() const
 {
-    ASSERT(mStorage);
-    return mStorage->getWidth();
+    return mWidth;
 }
 
 GLsizei Renderbuffer::getHeight() const
 {
-    ASSERT(mStorage);
-    return mStorage->getHeight();
+    return mHeight;
 }
 
 GLenum Renderbuffer::getInternalFormat() const
 {
-    ASSERT(mStorage);
-    return mStorage->getInternalFormat();
+    return mInternalFormat;
 }
 
 GLenum Renderbuffer::getActualFormat() const
 {
-    ASSERT(mStorage);
-    return mStorage->getActualFormat();
+    return mActualFormat;
 }
 
 GLsizei Renderbuffer::getSamples() const
 {
-    ASSERT(mStorage);
-    return mStorage->getSamples();
+    return mSamples;
 }
 
 GLuint Renderbuffer::getRedSize() const
@@ -107,176 +116,4 @@ GLuint Renderbuffer::getStencilSize() const
     return GetInternalFormatInfo(getActualFormat()).stencilBits;
 }
 
-RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerials(1))
-{
-    mWidth = 0;
-    mHeight = 0;
-    mInternalFormat = GL_RGBA4;
-    mActualFormat = GL_RGBA8_OES;
-    mSamples = 0;
-}
-
-RenderbufferStorage::~RenderbufferStorage()
-{
-}
-
-rx::RenderTarget *RenderbufferStorage::getRenderTarget()
-{
-    return NULL;
-}
-
-GLsizei RenderbufferStorage::getWidth() const
-{
-    return mWidth;
-}
-
-GLsizei RenderbufferStorage::getHeight() const
-{
-    return mHeight;
-}
-
-GLenum RenderbufferStorage::getInternalFormat() const
-{
-    return mInternalFormat;
-}
-
-GLenum RenderbufferStorage::getActualFormat() const
-{
-    return mActualFormat;
-}
-
-GLsizei RenderbufferStorage::getSamples() const
-{
-    return mSamples;
-}
-
-unsigned int RenderbufferStorage::getSerial() const
-{
-    return mSerial;
-}
-
-unsigned int RenderbufferStorage::issueSerials(unsigned int count)
-{
-    unsigned int firstSerial = mCurrentSerial;
-    mCurrentSerial += count;
-    return firstSerial;
-}
-
-bool RenderbufferStorage::isTexture() const
-{
-    return false;
-}
-
-unsigned int RenderbufferStorage::getTextureSerial() const
-{
-    return -1;
-}
-
-Colorbuffer::Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain)
-{
-    mRenderTarget = renderer->createRenderTarget(swapChain, false); 
-
-    if (mRenderTarget)
-    {
-        mWidth = mRenderTarget->getWidth();
-        mHeight = mRenderTarget->getHeight();
-        mInternalFormat = mRenderTarget->getInternalFormat();
-        mActualFormat = mRenderTarget->getActualFormat();
-        mSamples = mRenderTarget->getSamples();
-    }
-}
-
-Colorbuffer::Colorbuffer(rx::Renderer *renderer, int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL)
-{
-    mRenderTarget = renderer->createRenderTarget(width, height, format, samples);
-
-    if (mRenderTarget)
-    {
-        mWidth = width;
-        mHeight = height;
-        mInternalFormat = format;
-        mActualFormat = mRenderTarget->getActualFormat();
-        mSamples = mRenderTarget->getSamples();
-    }
-}
-
-Colorbuffer::~Colorbuffer()
-{
-    if (mRenderTarget)
-    {
-        delete mRenderTarget;
-    }
-}
-
-rx::RenderTarget *Colorbuffer::getRenderTarget()
-{
-    return mRenderTarget;
-}
-
-DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain)
-{
-    mDepthStencil = renderer->createRenderTarget(swapChain, true);
-    if (mDepthStencil)
-    {
-        mWidth = mDepthStencil->getWidth();
-        mHeight = mDepthStencil->getHeight();
-        mInternalFormat = mDepthStencil->getInternalFormat();
-        mSamples = mDepthStencil->getSamples();
-        mActualFormat = mDepthStencil->getActualFormat();
-    }
-}
-
-DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples)
-{
-
-    mDepthStencil = renderer->createRenderTarget(width, height, GL_DEPTH24_STENCIL8_OES, samples);
-
-    mWidth = mDepthStencil->getWidth();
-    mHeight = mDepthStencil->getHeight();
-    mInternalFormat = GL_DEPTH24_STENCIL8_OES;
-    mActualFormat = mDepthStencil->getActualFormat();
-    mSamples = mDepthStencil->getSamples();
-}
-
-DepthStencilbuffer::~DepthStencilbuffer()
-{
-    if (mDepthStencil)
-    {
-        delete mDepthStencil;
-    }
-}
-
-rx::RenderTarget *DepthStencilbuffer::getRenderTarget()
-{
-    return mDepthStencil;
-}
-
-Depthbuffer::Depthbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples)
-{
-    if (mDepthStencil)
-    {
-        mInternalFormat = GL_DEPTH_COMPONENT16;   // If the renderbuffer parameters are queried, the calling function
-                                                  // will expect one of the valid renderbuffer formats for use in 
-                                                  // glRenderbufferStorage
-    }
-}
-
-Depthbuffer::~Depthbuffer()
-{
-}
-
-Stencilbuffer::Stencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples)
-{
-    if (mDepthStencil)
-    {
-        mInternalFormat = GL_STENCIL_INDEX8;   // If the renderbuffer parameters are queried, the calling function
-                                               // will expect one of the valid renderbuffer formats for use in 
-                                               // glRenderbufferStorage
-    }
-}
-
-Stencilbuffer::~Stencilbuffer()
-{
-}
-
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h
index 71bcb0e1f84..e9f12af3ce1 100644
--- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h
@@ -4,30 +4,27 @@
 // found in the LICENSE file.
 //
 
-// Renderbuffer.h: Defines the wrapper class gl::Renderbuffer, as well as the
-// class hierarchy used to store its contents: RenderbufferStorage, Colorbuffer,
-// DepthStencilbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer
-// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
+// Renderbuffer.h: Defines the renderer-agnostic container class gl::Renderbuffer.
+// Implements GL renderbuffer objects and related functionality.
+// [OpenGL ES 2.0.24] section 4.4.3 page 108.
 
 #ifndef LIBGLESV2_RENDERBUFFER_H_
 #define LIBGLESV2_RENDERBUFFER_H_
 
 #include "angle_gl.h"
 
+#include "libGLESv2/Error.h"
+
 #include "common/angleutils.h"
 #include "common/RefCountObject.h"
 
 namespace rx
 {
-class Renderer;
-class SwapChain;
-class RenderTarget;
-class TextureStorage;
+class RenderbufferImpl;
 }
 
 namespace gl
 {
-class RenderbufferStorage;
 class FramebufferAttachment;
 
 // A GL renderbuffer object is usually used as a depth or stencil buffer attachment
@@ -38,11 +35,12 @@ class FramebufferAttachment;
 class Renderbuffer : public RefCountObject
 {
   public:
-    Renderbuffer(GLuint id, RenderbufferStorage *newStorage);
+    Renderbuffer(rx::RenderbufferImpl *impl, GLuint id);
     virtual ~Renderbuffer();
 
-    void setStorage(RenderbufferStorage *newStorage);
-    RenderbufferStorage *getStorage();
+    Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
+
+    rx::RenderbufferImpl *getImplementation();
 
     GLsizei getWidth() const;
     GLsizei getHeight() const;
@@ -57,102 +55,15 @@ class Renderbuffer : public RefCountObject
     GLuint getStencilSize() const;
 
   private:
-    RenderbufferStorage *mStorage;
-};
-
-// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage
-// is called. The specific concrete type depends on whether the internal format is
-// colour depth, stencil or packed depth/stencil.
-class RenderbufferStorage
-{
-  public:
-    RenderbufferStorage();
+    DISALLOW_COPY_AND_ASSIGN(Renderbuffer);
 
-    virtual ~RenderbufferStorage() = 0;
+    rx::RenderbufferImpl *mRenderbuffer;
 
-    virtual rx::RenderTarget *getRenderTarget();
-
-    virtual GLsizei getWidth() const;
-    virtual GLsizei getHeight() const;
-    virtual GLenum getInternalFormat() const;
-    virtual GLenum getActualFormat() const;
-    virtual GLsizei getSamples() const;
-
-    virtual unsigned int getSerial() const;
-
-    virtual bool isTexture() const;
-    virtual unsigned int getTextureSerial() const;
-
-    static unsigned int issueSerials(unsigned int count);
-
-  protected:
     GLsizei mWidth;
     GLsizei mHeight;
     GLenum mInternalFormat;
     GLenum mActualFormat;
     GLsizei mSamples;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage);
-
-    const unsigned int mSerial;
-
-    static unsigned int mCurrentSerial;
-};
-
-class Colorbuffer : public RenderbufferStorage
-{
-  public:
-    Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain);
-    Colorbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples);
-
-    virtual ~Colorbuffer();
-
-    virtual rx::RenderTarget *getRenderTarget();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Colorbuffer);
-
-    rx::RenderTarget *mRenderTarget;
-};
-
-class DepthStencilbuffer : public RenderbufferStorage
-{
-  public:
-    DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain);
-    DepthStencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples);
-
-    ~DepthStencilbuffer();
-
-    virtual rx::RenderTarget *getRenderTarget();
-
-  protected:
-    rx::RenderTarget  *mDepthStencil;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer);
-};
-
-class Depthbuffer : public DepthStencilbuffer
-{
-  public:
-    Depthbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples);
-
-    virtual ~Depthbuffer();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Depthbuffer);
-};
-
-class Stencilbuffer : public DepthStencilbuffer
-{
-  public:
-    Stencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples);
-
-    virtual ~Stencilbuffer();
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp
index 9121de1750f..38d53cad81e 100644
--- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp
@@ -21,9 +21,9 @@
 namespace gl
 {
 ResourceManager::ResourceManager(rx::Renderer *renderer)
+    : mRenderer(renderer),
+      mRefCount(1)
 {
-    mRefCount = 1;
-    mRenderer = renderer;
 }
 
 ResourceManager::~ResourceManager()
@@ -88,13 +88,13 @@ GLuint ResourceManager::createBuffer()
 }
 
 // Returns an unused shader/program name
-GLuint ResourceManager::createShader(GLenum type)
+GLuint ResourceManager::createShader(const gl::Data &data, GLenum type)
 {
     GLuint handle = mProgramShaderHandleAllocator.allocate();
 
     if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER)
     {
-        mShaderMap[handle] = new Shader(this, mRenderer->createShader(type), type, handle);
+        mShaderMap[handle] = new Shader(this, mRenderer->createShader(data, type), type, handle);
     }
     else UNREACHABLE();
 
@@ -146,7 +146,7 @@ GLuint ResourceManager::createFenceSync()
 {
     GLuint handle = mFenceSyncHandleAllocator.allocate();
 
-    FenceSync *fenceSync = new FenceSync(mRenderer, handle);
+    FenceSync *fenceSync = new FenceSync(mRenderer->createFenceSync(), handle);
     fenceSync->addRef();
     mFenceSyncMap[handle] = fenceSync;
 
@@ -295,9 +295,9 @@ Texture *ResourceManager::getTexture(unsigned int handle)
     }
 }
 
-Program *ResourceManager::getProgram(unsigned int handle)
+Program *ResourceManager::getProgram(unsigned int handle) const
 {
-    ProgramMap::iterator program = mProgramMap.find(handle);
+    ProgramMap::const_iterator program = mProgramMap.find(handle);
 
     if (program == mProgramMap.end())
     {
@@ -403,7 +403,7 @@ void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer)
 {
     if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
     {
-        Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0));
+        Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer->createRenderbuffer(), renderbuffer);
         mRenderbufferMap[renderbuffer] = renderbufferObject;
         renderbufferObject->addRef();
     }
diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h
index 7d53bd48549..acad29b51d5 100644
--- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h
+++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h
@@ -32,6 +32,7 @@ class Texture;
 class Renderbuffer;
 class Sampler;
 class FenceSync;
+struct Data;
 
 class ResourceManager
 {
@@ -43,7 +44,7 @@ class ResourceManager
     void release();
 
     GLuint createBuffer();
-    GLuint createShader(GLenum type);
+    GLuint createShader(const gl::Data &data, GLenum type);
     GLuint createProgram();
     GLuint createTexture();
     GLuint createRenderbuffer();
@@ -60,7 +61,7 @@ class ResourceManager
 
     Buffer *getBuffer(GLuint handle);
     Shader *getShader(GLuint handle);
-    Program *getProgram(GLuint handle);
+    Program *getProgram(GLuint handle) const;
     Texture *getTexture(GLuint handle);
     Renderbuffer *getRenderbuffer(GLuint handle);
     Sampler *getSampler(GLuint handle);
@@ -78,8 +79,8 @@ class ResourceManager
   private:
     DISALLOW_COPY_AND_ASSIGN(ResourceManager);
 
-    std::size_t mRefCount;
     rx::Renderer *mRenderer;
+    std::size_t mRefCount;
 
     typedef std::unordered_map<GLuint, Buffer*> BufferMap;
     BufferMap mBufferMap;
diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp
index 4cf5251ff9d..1cc17a05013 100644
--- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp
@@ -118,9 +118,15 @@ void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
     getSourceImpl(mShader->getTranslatedSource(), bufSize, length, buffer);
 }
 
-void Shader::compile()
+void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const
 {
-    mCompiled = mShader->compile(mSource);
+    std::string debugInfo(mShader->getDebugInfo());
+    getSourceImpl(debugInfo, bufSize, length, buffer);
+}
+
+void Shader::compile(const gl::Data &data)
+{
+    mCompiled = mShader->compile(data, mSource);
 }
 
 void Shader::addRef()
diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h
index 7ba3bd165c3..904217dab8c 100644
--- a/src/3rdparty/angle/src/libGLESv2/Shader.h
+++ b/src/3rdparty/angle/src/libGLESv2/Shader.h
@@ -31,6 +31,7 @@ class ShaderImpl;
 namespace gl
 {
 class ResourceManager;
+struct Data;
 
 struct PackedVarying : public sh::Varying
 {
@@ -73,8 +74,9 @@ class Shader
     void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
     int getTranslatedSourceLength() const;
     void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
+    void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const;
 
-    void compile();
+    void compile(const gl::Data &data);
     bool isCompiled() const { return mCompiled; }
 
     void addRef();
diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libGLESv2/State.cpp
index 3c03b90e56b..b5b62f58483 100644
--- a/src/3rdparty/angle/src/libGLESv2/State.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/State.cpp
@@ -10,18 +10,20 @@
 
 #include "libGLESv2/Context.h"
 #include "libGLESv2/Caps.h"
-#include "libGLESv2/VertexArray.h"
-#include "libGLESv2/Query.h"
 #include "libGLESv2/Framebuffer.h"
 #include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/renderer/RenderTarget.h"
+#include "libGLESv2/Query.h"
+#include "libGLESv2/VertexArray.h"
 #include "libGLESv2/formatutils.h"
+#include "libGLESv2/renderer/RenderTarget.h"
 
 namespace gl
 {
 
 State::State()
 {
+    mMaxDrawBuffers = 0;
+    mMaxCombinedTextureImageUnits = 0;
 }
 
 State::~State()
@@ -31,7 +33,8 @@ State::~State()
 
 void State::initialize(const Caps& caps, GLuint clientVersion)
 {
-    mContext = NULL;
+    mMaxDrawBuffers = caps.maxDrawBuffers;
+    mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
 
     setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
@@ -111,11 +114,15 @@ void State::initialize(const Caps& caps, GLuint clientVersion)
     mActiveSampler = 0;
 
     const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f };
-    for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++)
+    mVertexAttribCurrentValues.resize(caps.maxVertexAttributes);
+    for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); ++attribIndex)
     {
         mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
     }
 
+    mUniformBuffers.resize(caps.maxCombinedUniformBlocks);
+    mTransformFeedbackBuffers.resize(caps.maxTransformFeedbackSeparateAttributes);
+
     mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits);
     mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits);
     if (clientVersion >= 3)
@@ -153,12 +160,6 @@ void State::reset()
         mSamplers[samplerIdx].set(NULL);
     }
 
-    const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f };
-    for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++)
-    {
-        mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
-    }
-
     mArrayBuffer.set(NULL);
     mRenderbuffer.set(NULL);
 
@@ -170,15 +171,15 @@ void State::reset()
     }
 
     mGenericUniformBuffer.set(NULL);
-    for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++)
+    mGenericTransformFeedbackBuffer.set(NULL);
+    for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr)
     {
-        mUniformBuffers[i].set(NULL);
+        bufItr->set(NULL);
     }
 
-    mGenericTransformFeedbackBuffer.set(NULL);
-    for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
+    for (BufferVector::iterator bufItr = mTransformFeedbackBuffers.begin(); bufItr != mTransformFeedbackBuffers.end(); ++bufItr)
     {
-        mTransformFeedbackBuffers[i].set(NULL);
+        bufItr->set(NULL);
     }
 
     mCopyReadBuffer.set(NULL);
@@ -485,7 +486,7 @@ void State::setSampleCoverageParams(GLclampf value, bool invert)
     mSampleCoverageInvert = invert;
 }
 
-void State::getSampleCoverageParams(GLclampf *value, bool *invert)
+void State::getSampleCoverageParams(GLclampf *value, bool *invert) const
 {
     ASSERT(value != NULL && invert != NULL);
 
@@ -612,14 +613,7 @@ void State::setSamplerTexture(GLenum type, Texture *texture)
 
 Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const
 {
-    const BindingPointer<Texture>& binding = mSamplerTextures.at(type)[sampler];
-
-    if (binding.id() == 0)   // Special case: 0 refers to default textures held by Context
-    {
-        return NULL;
-    }
-
-    return binding.get();
+    return mSamplerTextures.at(type)[sampler].get();
 }
 
 GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const
@@ -627,7 +621,7 @@ GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const
     return mSamplerTextures.at(type)[sampler].id();
 }
 
-void State::detachTexture(GLuint texture)
+void State::detachTexture(const TextureMap &zeroTextures, GLuint texture)
 {
     // Textures have a detach method on State rather than a simple
     // removeBinding, because the zero/null texture objects are managed
@@ -640,13 +634,15 @@ void State::detachTexture(GLuint texture)
 
     for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++)
     {
+        GLenum textureType = bindingVec->first;
         TextureBindingVector &textureVector = bindingVec->second;
         for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
         {
             BindingPointer<Texture> &binding = textureVector[textureIdx];
             if (binding.id() == texture)
             {
-                binding.set(NULL);
+                // Zero textures are the "default" textures instead of NULL
+                binding.set(zeroTextures.at(textureType).get());
             }
         }
     }
@@ -667,6 +663,19 @@ void State::detachTexture(GLuint texture)
     }
 }
 
+void State::initializeZeroTextures(const TextureMap &zeroTextures)
+{
+    for (TextureMap::const_iterator i = zeroTextures.begin(); i != zeroTextures.end(); i++)
+    {
+        TextureBindingVector &samplerTextureArray = mSamplerTextures[i->first];
+
+        for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit)
+        {
+            samplerTextureArray[textureUnit].set(i->second.get());
+        }
+    }
+}
+
 void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler)
 {
     mSamplers[textureUnit].set(sampler);
@@ -947,14 +956,14 @@ void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintpt
 
 GLuint State::getIndexedUniformBufferId(GLuint index) const
 {
-    ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
+    ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
 
     return mUniformBuffers[index].id();
 }
 
 Buffer *State::getIndexedUniformBuffer(GLuint index) const
 {
-    ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
+    ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
 
     return mUniformBuffers[index].get();
 }
@@ -971,25 +980,30 @@ void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffe
 
 GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const
 {
-    ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
+    ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size());
 
     return mTransformFeedbackBuffers[index].id();
 }
 
 Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const
 {
-    ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
+    ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size());
 
     return mTransformFeedbackBuffers[index].get();
 }
 
 GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const
 {
-    ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
+    ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size());
 
     return mTransformFeedbackBuffers[index].getOffset();
 }
 
+size_t State::getTransformFeedbackBufferIndexRange() const
+{
+    return mTransformFeedbackBuffers.size();
+}
+
 void State::setCopyReadBufferBinding(Buffer *buffer)
 {
     mCopyReadBuffer.set(buffer);
@@ -1033,19 +1047,19 @@ void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
 
 void State::setVertexAttribf(GLuint index, const GLfloat values[4])
 {
-    ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
+    ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
     mVertexAttribCurrentValues[index].setFloatValues(values);
 }
 
 void State::setVertexAttribu(GLuint index, const GLuint values[4])
 {
-    ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
+    ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
     mVertexAttribCurrentValues[index].setUnsignedIntValues(values);
 }
 
 void State::setVertexAttribi(GLuint index, const GLint values[4])
 {
-    ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
+    ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
     mVertexAttribCurrentValues[index].setIntValues(values);
 }
 
@@ -1062,15 +1076,10 @@ const VertexAttribute &State::getVertexAttribState(unsigned int attribNum) const
 
 const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const
 {
-    ASSERT(attribNum < MAX_VERTEX_ATTRIBS);
+    ASSERT(static_cast<size_t>(attribNum) < mVertexAttribCurrentValues.size());
     return mVertexAttribCurrentValues[attribNum];
 }
 
-const VertexAttribCurrentValueData *State::getVertexAttribCurrentValues() const
-{
-    return mVertexAttribCurrentValues;
-}
-
 const void *State::getVertexAttribPointer(unsigned int attribNum) const
 {
     return getVertexArray()->getVertexAttribute(attribNum).pointer;
@@ -1180,12 +1189,12 @@ void State::getFloatv(GLenum pname, GLfloat *params)
     }
 }
 
-void State::getIntegerv(GLenum pname, GLint *params)
+void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
 {
     if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
     {
         unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT);
-        ASSERT(colorAttachment < mContext->getCaps().maxDrawBuffers);
+        ASSERT(colorAttachment < mMaxDrawBuffers);
         Framebuffer *framebuffer = mDrawFramebuffer;
         *params = framebuffer->getDrawBufferState(colorAttachment);
         return;
@@ -1238,12 +1247,12 @@ void State::getIntegerv(GLenum pname, GLint *params)
       case GL_SAMPLES:
         {
             gl::Framebuffer *framebuffer = mDrawFramebuffer;
-            if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
+            if (framebuffer->completeness(data) == GL_FRAMEBUFFER_COMPLETE)
             {
                 switch (pname)
                 {
                   case GL_SAMPLE_BUFFERS:
-                    if (framebuffer->getSamples() != 0)
+                    if (framebuffer->getSamples(data) != 0)
                     {
                         *params = 1;
                     }
@@ -1253,7 +1262,7 @@ void State::getIntegerv(GLenum pname, GLint *params)
                     }
                     break;
                   case GL_SAMPLES:
-                    *params = framebuffer->getSamples();
+                    *params = framebuffer->getSamples(data);
                     break;
                 }
             }
@@ -1332,19 +1341,19 @@ void State::getIntegerv(GLenum pname, GLint *params)
         }
         break;
       case GL_TEXTURE_BINDING_2D:
-        ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
+        ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
         *params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id();
         break;
       case GL_TEXTURE_BINDING_CUBE_MAP:
-        ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
+        ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
         *params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id();
         break;
       case GL_TEXTURE_BINDING_3D:
-        ASSERT(mActiveSampler <mContext->getCaps().maxCombinedTextureImageUnits);
+        ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
         *params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id();
         break;
       case GL_TEXTURE_BINDING_2D_ARRAY:
-        ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
+        ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
         *params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id();
         break;
       case GL_UNIFORM_BUFFER_BINDING:
@@ -1376,13 +1385,13 @@ bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
     switch (target)
     {
       case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
-        if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS)
+        if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size())
         {
             *data = mTransformFeedbackBuffers[index].id();
         }
         break;
       case GL_UNIFORM_BUFFER_BINDING:
-        if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS)
+        if (static_cast<size_t>(index) < mUniformBuffers.size())
         {
             *data = mUniformBuffers[index].id();
         }
@@ -1399,25 +1408,25 @@ bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
     switch (target)
     {
       case GL_TRANSFORM_FEEDBACK_BUFFER_START:
-        if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS)
+        if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size())
         {
             *data = mTransformFeedbackBuffers[index].getOffset();
         }
         break;
       case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
-        if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS)
+        if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size())
         {
             *data = mTransformFeedbackBuffers[index].getSize();
         }
         break;
       case GL_UNIFORM_BUFFER_START:
-        if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS)
+        if (static_cast<size_t>(index) < mUniformBuffers.size())
         {
             *data = mUniformBuffers[index].getOffset();
         }
         break;
       case GL_UNIFORM_BUFFER_SIZE:
-        if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS)
+        if (static_cast<size_t>(index) < mUniformBuffers.size())
         {
             *data = mUniformBuffers[index].getSize();
         }
@@ -1433,9 +1442,9 @@ bool State::hasMappedBuffer(GLenum target) const
 {
     if (target == GL_ARRAY_BUFFER)
     {
-        for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++)
+        for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); attribIndex++)
         {
-            const gl::VertexAttribute &vertexAttrib = getVertexAttribState(attribIndex);
+            const gl::VertexAttribute &vertexAttrib = getVertexAttribState(static_cast<unsigned int>(attribIndex));
             gl::Buffer *boundBuffer = vertexAttrib.buffer.get();
             if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped())
             {
diff --git a/src/3rdparty/angle/src/libGLESv2/State.h b/src/3rdparty/angle/src/libGLESv2/State.h
index 5f0433136c3..c3e6106bd84 100644
--- a/src/3rdparty/angle/src/libGLESv2/State.h
+++ b/src/3rdparty/angle/src/libGLESv2/State.h
@@ -25,6 +25,9 @@ class Query;
 class VertexArray;
 class Context;
 struct Caps;
+struct Data;
+
+typedef std::map< GLenum, BindingPointer<Texture> > TextureMap;
 
 class State
 {
@@ -35,8 +38,6 @@ class State
     void initialize(const Caps& caps, GLuint clientVersion);
     void reset();
 
-    void setContext(Context *context) { mContext = context; }
-
     // State chunk getters
     const RasterizerState &getRasterizerState() const;
     const BlendState &getBlendState() const;
@@ -100,7 +101,7 @@ class State
     bool isSampleCoverageEnabled() const;
     void setSampleCoverage(bool enabled);
     void setSampleCoverageParams(GLclampf value, bool invert);
-    void getSampleCoverageParams(GLclampf *value, bool *invert);
+    void getSampleCoverageParams(GLclampf *value, bool *invert) const;
 
     // Scissor test state toggle & query
     bool isScissorTestEnabled() const;
@@ -133,7 +134,8 @@ class State
     void setSamplerTexture(GLenum type, Texture *texture);
     Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
     GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const;
-    void detachTexture(GLuint texture);
+    void detachTexture(const TextureMap &zeroTextures, GLuint texture);
+    void initializeZeroTextures(const TextureMap &zeroTextures);
 
     // Sampler object binding manipulation
     void setSamplerBinding(GLuint textureUnit, Sampler *sampler);
@@ -199,6 +201,7 @@ class State
     GLuint getIndexedTransformFeedbackBufferId(GLuint index) const;
     Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const;
     GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const;
+    size_t getTransformFeedbackBufferIndexRange() const;
 
     // GL_COPY_[READ/WRITE]_BUFFER
     void setCopyReadBufferBinding(Buffer *buffer);
@@ -220,7 +223,6 @@ class State
                               bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
     const VertexAttribute &getVertexAttribState(unsigned int attribNum) const;
     const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const;
-    const VertexAttribCurrentValueData *getVertexAttribCurrentValues() const;
     const void *getVertexAttribPointer(unsigned int attribNum) const;
 
     // Pixel pack state manipulation
@@ -238,7 +240,7 @@ class State
     // State query functions
     void getBooleanv(GLenum pname, GLboolean *params);
     void getFloatv(GLenum pname, GLfloat *params);
-    void getIntegerv(GLenum pname, GLint *params);
+    void getIntegerv(const gl::Data &data, GLenum pname, GLint *params);
     bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data);
     bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data);
 
@@ -247,7 +249,9 @@ class State
   private:
     DISALLOW_COPY_AND_ASSIGN(State);
 
-    Context *mContext;
+    // Cached values from Context's caps
+    GLuint mMaxDrawBuffers;
+    GLuint mMaxCombinedTextureImageUnits;
 
     ColorF mColorClearValue;
     GLclampf mDepthClearValue;
@@ -283,7 +287,8 @@ class State
     GLuint mCurrentProgramId;
     BindingPointer<ProgramBinary> mCurrentProgramBinary;
 
-    VertexAttribCurrentValueData mVertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib
+    typedef std::vector<VertexAttribCurrentValueData> VertexAttribVector;
+    VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib
     VertexArray *mVertexArray;
 
     // Texture and sampler bindings
@@ -300,11 +305,12 @@ class State
     ActiveQueryMap mActiveQueries;
 
     BindingPointer<Buffer> mGenericUniformBuffer;
-    OffsetBindingPointer<Buffer> mUniformBuffers[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
+    typedef std::vector< OffsetBindingPointer<Buffer> > BufferVector;
+    BufferVector mUniformBuffers;
 
     BindingPointer<TransformFeedback> mTransformFeedback;
     BindingPointer<Buffer> mGenericTransformFeedbackBuffer;
-    OffsetBindingPointer<Buffer> mTransformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
+    BufferVector mTransformFeedbackBuffers;
 
     BindingPointer<Buffer> mCopyReadBuffer;
     BindingPointer<Buffer> mCopyWriteBuffer;
diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp
index 3ec492de077..cd4fc4e32a6 100644
--- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp
@@ -47,11 +47,14 @@ bool IsPointSampled(const gl::SamplerState &samplerState)
     return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
 }
 
+unsigned int Texture::mCurrentTextureSerial = 1;
+
 Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
     : RefCountObject(id),
       mTexture(impl),
+      mTextureSerial(issueTextureSerial()),
       mUsage(GL_NONE),
-      mImmutable(false),
+      mImmutableLevelCount(0),
       mTarget(target)
 {
 }
@@ -72,16 +75,6 @@ void Texture::setUsage(GLenum usage)
     getImplementation()->setUsage(usage);
 }
 
-void Texture::getSamplerStateWithNativeOffset(SamplerState *sampler)
-{
-    *sampler = mSamplerState;
-
-    // Offset the effective base level by the texture storage's top level
-    rx::TextureStorage *texture = getNativeTexture();
-    int topLevel = texture ? texture->getTopLevel() : 0;
-    sampler->baseLevel = topLevel + mSamplerState.baseLevel;
-}
-
 GLenum Texture::getUsage() const
 {
     return mUsage;
@@ -138,35 +131,35 @@ GLenum Texture::getActualFormat(const ImageIndex &index) const
     return image->getActualFormat();
 }
 
-rx::TextureStorage *Texture::getNativeTexture()
+Error Texture::generateMipmaps()
 {
-    return getImplementation()->getNativeTexture();
+    return getImplementation()->generateMipmaps();
 }
 
-void Texture::generateMipmaps()
+Error Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                           GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
 {
-    getImplementation()->generateMipmaps();
+    return mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
 }
 
-void Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
+unsigned int Texture::getTextureSerial() const
 {
-    getImplementation()->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
+    return mTextureSerial;
 }
 
-unsigned int Texture::getTextureSerial()
+unsigned int Texture::issueTextureSerial()
 {
-    rx::TextureStorage *texture = getNativeTexture();
-    return texture ? texture->getTextureSerial() : 0;
+    return mCurrentTextureSerial++;
 }
 
 bool Texture::isImmutable() const
 {
-    return mImmutable;
+    return (mImmutableLevelCount > 0);
 }
 
 int Texture::immutableLevelCount()
 {
-    return (mImmutable ? getNativeTexture()->getLevelCount() : 0);
+    return mImmutableLevelCount;
 }
 
 int Texture::mipLevels() const
@@ -226,11 +219,11 @@ GLenum Texture2D::getActualFormat(GLint level) const
         return GL_NONE;
 }
 
-void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
     releaseTexImage();
 
-    mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels);
+    return mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels);
 }
 
 void Texture2D::bindTexImage(egl::Surface *surface)
@@ -254,35 +247,44 @@ void Texture2D::releaseTexImage()
     }
 }
 
-void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
+Error Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize,
+                                    const PixelUnpackState &unpack, const void *pixels)
 {
     releaseTexImage();
 
-    mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, pixels);
+    return mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, unpack, pixels);
 }
 
-void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
+    return mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
 }
 
-void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
+Error Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                    GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels);
+    return mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels);
 }
 
-void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
+Error Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height,
+                           Framebuffer *source)
 {
     releaseTexImage();
 
-    mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source);
+    return mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source);
 }
 
-void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+Error Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
 {
-    mImmutable = true;
+    Error error = mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    mImmutableLevelCount = levels;
 
-    mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1);
+    return Error(GL_NO_ERROR);
 }
 
 // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
@@ -359,11 +361,11 @@ bool Texture2D::isDepth(GLint level) const
     return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
-void Texture2D::generateMipmaps()
+Error Texture2D::generateMipmaps()
 {
     releaseTexImage();
 
-    mTexture->generateMipmaps();
+    return mTexture->generateMipmaps();
 }
 
 // Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
@@ -467,49 +469,27 @@ GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const
         return GL_NONE;
 }
 
-void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
-    mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels);
-}
-
-void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
-    mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels);
-}
-
-void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
-    mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels);
-}
-
-void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
-    mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels);
-}
-
-void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error TextureCubeMap::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels);
+    return mTexture->setImage(target, level, width, height, 1, internalFormat, format, type, unpack, pixels);
 }
 
-void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height,
+                                         GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels);
+    return mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, unpack, pixels);
 }
 
-void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
+Error TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, pixels);
+    return mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
 }
 
-void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset,
+                                         GLsizei width, GLsizei height, GLenum format,
+                                         GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
-}
-
-void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
-{
-    mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels);
+    return mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels);
 }
 
 // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
@@ -549,16 +529,23 @@ bool TextureCubeMap::isDepth(GLenum target, GLint level) const
     return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0;
 }
 
-void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
+Error TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y,
+                                GLsizei width, GLsizei height, Framebuffer *source)
 {
-    mTexture->copyImage(target, level, format, x, y, width, height, source);
+    return mTexture->copyImage(target, level, format, x, y, width, height, source);
 }
 
-void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
+Error TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
 {
-    mImmutable = true;
+    Error error = mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    mImmutableLevelCount = levels;
 
-    mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1);
+    return Error(GL_NO_ERROR);
 }
 
 // Tests for texture sampling completeness
@@ -734,31 +721,40 @@ bool Texture3D::isDepth(GLint level) const
     return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
-void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels);
+    return mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels);
 }
 
-void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+Error Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth,
+                                    GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, pixels);
+    return mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, unpack, pixels);
 }
 
-void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
+    return mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
 }
 
-void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
+Error Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                    GLsizei width, GLsizei height, GLsizei depth, GLenum format,
+                                    GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
+    return mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels);
 }
 
-void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+Error Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
 {
-    mImmutable = true;
+    Error error = mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth);
+    mImmutableLevelCount = levels;
+
+    return Error(GL_NO_ERROR);
 }
 
 bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
@@ -892,31 +888,40 @@ bool Texture2DArray::isDepth(GLint level) const
     return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
-void Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels);
+    return mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels);
 }
 
-void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+Error Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth,
+                                         GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, pixels);
+    return mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, unpack, pixels);
 }
 
-void Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
+    return mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
 }
 
-void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
+Error Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                         GLsizei width, GLsizei height, GLsizei depth, GLenum format,
+                                         GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
+    return mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels);
 }
 
-void Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+Error Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
 {
-    mImmutable = true;
+    Error error = mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    mImmutableLevelCount = levels;
 
-    mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth);
+    return Error(GL_NO_ERROR);
 }
 
 bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.h b/src/3rdparty/angle/src/libGLESv2/Texture.h
index ca5686fde3e..66d4df80158 100644
--- a/src/3rdparty/angle/src/libGLESv2/Texture.h
+++ b/src/3rdparty/angle/src/libGLESv2/Texture.h
@@ -14,7 +14,7 @@
 #include "common/debug.h"
 #include "common/RefCountObject.h"
 #include "libGLESv2/angletypes.h"
-#include "libGLESv2/constants.h"
+#include "libGLESv2/Constants.h"
 #include "libGLESv2/renderer/TextureImpl.h"
 #include "libGLESv2/Caps.h"
 
@@ -52,7 +52,6 @@ class Texture : public RefCountObject
 
     const SamplerState &getSamplerState() const { return mSamplerState; }
     SamplerState &getSamplerState() { return mSamplerState; }
-    void getSamplerStateWithNativeOffset(SamplerState *sampler);
 
     void setUsage(GLenum usage);
     GLenum getUsage() const;
@@ -69,15 +68,16 @@ class Texture : public RefCountObject
 
     virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const = 0;
 
-    rx::TextureStorage *getNativeTexture();
+    virtual Error generateMipmaps();
 
-    virtual void generateMipmaps();
-    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+    virtual Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
 
-    unsigned int getTextureSerial();
+    // Texture serials provide a unique way of identifying a Texture that isn't a raw pointer.
+    // "id" is not good enough, as Textures can be deleted, then re-allocated with the same id.
+    unsigned int getTextureSerial() const;
 
     bool isImmutable() const;
-    int immutableLevelCount();
+    GLsizei immutableLevelCount();
 
     rx::TextureImpl *getImplementation() { return mTexture; }
     const rx::TextureImpl *getImplementation() const { return mTexture; }
@@ -86,17 +86,20 @@ class Texture : public RefCountObject
 
   protected:
     int mipLevels() const;
+    const rx::Image *getBaseLevelImage() const;
+    static unsigned int issueTextureSerial();
 
     rx::TextureImpl *mTexture;
 
     SamplerState mSamplerState;
     GLenum mUsage;
 
-    bool mImmutable;
+    GLsizei mImmutableLevelCount;
 
     GLenum mTarget;
 
-    const rx::Image *getBaseLevelImage() const;
+    const unsigned int mTextureSerial;
+    static unsigned int mCurrentTextureSerial;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Texture);
@@ -116,18 +119,18 @@ class Texture2D : public Texture
     bool isCompressed(GLint level) const;
     bool isDepth(GLint level) const;
 
-    void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
-    void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
-    void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
-    void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+    Error setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
+    Error subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
+    Error copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+    Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
 
     virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
     virtual void bindTexImage(egl::Surface *surface);
     virtual void releaseTexImage();
 
-    virtual void generateMipmaps();
+    virtual Error generateMipmaps();
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Texture2D);
@@ -152,19 +155,12 @@ class TextureCubeMap : public Texture
     bool isCompressed(GLenum target, GLint level) const;
     bool isDepth(GLenum target, GLint level) const;
 
-    void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-
-    void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
-
-    void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
-    void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
-    void storage(GLsizei levels, GLenum internalformat, GLsizei size);
+    Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
+    Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
+    Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+    Error storage(GLsizei levels, GLenum internalformat, GLsizei size);
 
     virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
 
@@ -195,11 +191,11 @@ class Texture3D : public Texture
     bool isCompressed(GLint level) const;
     bool isDepth(GLint level) const;
 
-    void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
-    void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
-    void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+    Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
+    Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
+    Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 
     virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
 
@@ -225,11 +221,11 @@ class Texture2DArray : public Texture
     bool isCompressed(GLint level) const;
     bool isDepth(GLint level) const;
 
-    void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
-    void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
-    void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+    Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
+    Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
+    Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 
     virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
 
diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.h b/src/3rdparty/angle/src/libGLESv2/VertexArray.h
index 993ba042cfd..a724c0be1cb 100644
--- a/src/3rdparty/angle/src/libGLESv2/VertexArray.h
+++ b/src/3rdparty/angle/src/libGLESv2/VertexArray.h
@@ -14,14 +14,13 @@
 #define LIBGLESV2_VERTEXARRAY_H_
 
 #include "common/RefCountObject.h"
-#include "libGLESv2/constants.h"
+#include "libGLESv2/Constants.h"
 #include "libGLESv2/VertexAttribute.h"
 
 #include <vector>
 
 namespace rx
 {
-class Renderer;
 class VertexArrayImpl;
 }
 
@@ -44,7 +43,7 @@ class VertexArray
     void setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type,
                            bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
 
-    const VertexAttribute* getVertexAttributes() const { return mVertexAttributes.data(); }
+    const VertexAttribute* getVertexAttributes() const { return &mVertexAttributes[0]; }
     Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); }
     void setElementArrayBuffer(Buffer *buffer);
     GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); }
diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp
index bb6425df647..5a0cfc5ad95 100644
--- a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp
@@ -9,6 +9,10 @@
 #include "libGLESv2/angletypes.h"
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/VertexAttribute.h"
+#include "libGLESv2/State.h"
+#include "libGLESv2/VertexArray.h"
+
+#include <float.h>
 
 namespace gl
 {
@@ -148,16 +152,16 @@ VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueTyp
 
 void VertexFormat::GetInputLayout(VertexFormat *inputLayout,
                                   ProgramBinary *programBinary,
-                                  const VertexAttribute *attributes,
-                                  const gl::VertexAttribCurrentValueData *currentValues)
+                                  const State &state)
 {
+    const VertexAttribute *vertexAttributes = state.getVertexArray()->getVertexAttributes();
     for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
     {
         int semanticIndex = programBinary->getSemanticIndex(attributeIndex);
 
         if (semanticIndex != -1)
         {
-            inputLayout[semanticIndex] = VertexFormat(attributes[attributeIndex], currentValues[attributeIndex].Type);
+            inputLayout[semanticIndex] = VertexFormat(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex).Type);
         }
     }
 }
@@ -192,4 +196,15 @@ bool VertexFormat::operator<(const VertexFormat& other) const
     return mPureInteger < other.mPureInteger;
 }
 
+bool Box::operator==(const Box &other) const
+{
+    return (x == other.x && y == other.y && z == other.z &&
+            width == other.width && height == other.height && depth == other.depth);
+}
+
+bool Box::operator!=(const Box &other) const
+{
+    return !(*this == other);
+}
+
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libGLESv2/angletypes.h
index 642a6ec266d..78fe6b0e263 100644
--- a/src/3rdparty/angle/src/libGLESv2/angletypes.h
+++ b/src/3rdparty/angle/src/libGLESv2/angletypes.h
@@ -9,13 +9,13 @@
 #ifndef LIBGLESV2_ANGLETYPES_H_
 #define LIBGLESV2_ANGLETYPES_H_
 
-#include "libGLESv2/constants.h"
+#include "libGLESv2/Constants.h"
 #include "common/RefCountObject.h"
-#include <float.h>
 
 namespace gl
 {
 class Buffer;
+class State;
 class ProgramBinary;
 struct VertexAttribute;
 struct VertexAttribCurrentValueData;
@@ -66,6 +66,8 @@ struct Box
 
     Box() : x(0), y(0), z(0), width(0), height(0), depth(0) { }
     Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in) : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in) { }
+    bool operator==(const Box &other) const;
+    bool operator!=(const Box &other) const;
 };
 
 struct Extents
@@ -230,8 +232,7 @@ struct VertexFormat
 
     static void GetInputLayout(VertexFormat *inputLayout,
                                ProgramBinary *programBinary,
-                               const VertexAttribute *attributes,
-                               const gl::VertexAttribCurrentValueData *currentValues);
+                               const State& currentValues);
 
     bool operator==(const VertexFormat &other) const;
     bool operator!=(const VertexFormat &other) const;
@@ -251,13 +252,6 @@ enum VertexConversionType
     VERTEX_CONVERT_BOTH = 3
 };
 
-enum D3DWorkaroundType
-{
-    ANGLE_D3D_WORKAROUND_NONE,
-    ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION,
-    ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION
-};
-
 }
 
 #endif // LIBGLESV2_ANGLETYPES_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
index 07f5d47473d..587950a1397 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
@@ -34,13 +34,12 @@
 #include "libGLESv2/validationES3.h"
 #include "libGLESv2/queryconversions.h"
 
-
 extern "C"
 {
 
 // OpenGL ES 2.0 functions
 
-void __stdcall glActiveTexture(GLenum texture)
+void GL_APIENTRY glActiveTexture(GLenum texture)
 {
     EVENT("(GLenum texture = 0x%X)", texture);
 
@@ -57,7 +56,7 @@ void __stdcall glActiveTexture(GLenum texture)
     }
 }
 
-void __stdcall glAttachShader(GLuint program, GLuint shader)
+void GL_APIENTRY glAttachShader(GLuint program, GLuint shader)
 {
     EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
 
@@ -103,7 +102,7 @@ void __stdcall glAttachShader(GLuint program, GLuint shader)
     }
 }
 
-void __stdcall glBeginQueryEXT(GLenum target, GLuint id)
+void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id)
 {
     EVENT("(GLenum target = 0x%X, GLuint %d)", target, id);
 
@@ -124,7 +123,7 @@ void __stdcall glBeginQueryEXT(GLenum target, GLuint id)
     }
 }
 
-void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
+void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
 {
     EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
 
@@ -163,7 +162,7 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar*
     }
 }
 
-void __stdcall glBindBuffer(GLenum target, GLuint buffer)
+void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer)
 {
     EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
 
@@ -210,7 +209,7 @@ void __stdcall glBindBuffer(GLenum target, GLuint buffer)
     }
 }
 
-void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer)
+void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer)
 {
     EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
 
@@ -235,7 +234,7 @@ void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer)
     }
 }
 
-void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer)
+void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer)
 {
     EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
 
@@ -252,7 +251,7 @@ void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer)
     }
 }
 
-void __stdcall glBindTexture(GLenum target, GLuint texture)
+void GL_APIENTRY glBindTexture(GLenum target, GLuint texture)
 {
     EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
 
@@ -291,7 +290,7 @@ void __stdcall glBindTexture(GLenum target, GLuint texture)
     }
 }
 
-void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+void GL_APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
 {
     EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
           red, green, blue, alpha);
@@ -304,12 +303,12 @@ void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp
     }
 }
 
-void __stdcall glBlendEquation(GLenum mode)
+void GL_APIENTRY glBlendEquation(GLenum mode)
 {
     glBlendEquationSeparate(mode, mode);
 }
 
-void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+void GL_APIENTRY glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
 {
     EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
 
@@ -348,12 +347,12 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
     }
 }
 
-void __stdcall glBlendFunc(GLenum sfactor, GLenum dfactor)
+void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
 {
     glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
 }
 
-void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+void GL_APIENTRY glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
 {
     EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
           srcRGB, dstRGB, srcAlpha, dstAlpha);
@@ -488,7 +487,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha
     }
 }
 
-void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
 {
     EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
           target, size, data, usage);
@@ -550,7 +549,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
     }
 }
 
-void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
+void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
 {
     EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
           target, offset, size, data);
@@ -611,7 +610,7 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
     }
 }
 
-GLenum __stdcall glCheckFramebufferStatus(GLenum target)
+GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum target)
 {
     EVENT("(GLenum target = 0x%X)", target);
 
@@ -626,13 +625,14 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target)
 
         gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
         ASSERT(framebuffer);
-        return framebuffer->completeness();
+
+        return framebuffer->completeness(context->getData());
     }
 
     return 0;
 }
 
-void __stdcall glClear(GLbitfield mask)
+void GL_APIENTRY glClear(GLbitfield mask)
 {
     EVENT("(GLbitfield mask = 0x%X)", mask);
 
@@ -640,8 +640,9 @@ void __stdcall glClear(GLbitfield mask)
     if (context)
     {
         gl::Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
+        ASSERT(framebufferObject);
 
-        if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
+        if (framebufferObject->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
         {
             context->recordError(gl::Error(GL_INVALID_FRAMEBUFFER_OPERATION));
             return;
@@ -662,7 +663,7 @@ void __stdcall glClear(GLbitfield mask)
     }
 }
 
-void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
 {
     EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
           red, green, blue, alpha);
@@ -674,7 +675,7 @@ void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp
     }
 }
 
-void __stdcall glClearDepthf(GLclampf depth)
+void GL_APIENTRY glClearDepthf(GLclampf depth)
 {
     EVENT("(GLclampf depth = %f)", depth);
 
@@ -685,7 +686,7 @@ void __stdcall glClearDepthf(GLclampf depth)
     }
 }
 
-void __stdcall glClearStencil(GLint s)
+void GL_APIENTRY glClearStencil(GLint s)
 {
     EVENT("(GLint s = %d)", s);
 
@@ -696,7 +697,7 @@ void __stdcall glClearStencil(GLint s)
     }
 }
 
-void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
 {
     EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)",
           red, green, blue, alpha);
@@ -708,7 +709,7 @@ void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboo
     }
 }
 
-void __stdcall glCompileShader(GLuint shader)
+void GL_APIENTRY glCompileShader(GLuint shader)
 {
     EVENT("(GLuint shader = %d)", shader);
 
@@ -731,11 +732,11 @@ void __stdcall glCompileShader(GLuint shader)
             }
         }
 
-        shaderObject->compile();
+        shaderObject->compile(context->getData());
     }
 }
 
-void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
+void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
                                       GLint border, GLsizei imageSize, const GLvoid* data)
 {
     EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
@@ -771,7 +772,12 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
           case GL_TEXTURE_2D:
             {
                 gl::Texture2D *texture = context->getTexture2D();
-                texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
+                gl::Error error = texture->setCompressedImage(level, internalformat, width, height, imageSize, context->getState().getUnpackState(), data);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -783,7 +789,12 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
           case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
             {
                 gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
+                gl::Error error = texture->setCompressedImage(target, level, internalformat, width, height, imageSize, context->getState().getUnpackState(), data);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -794,7 +805,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
     }
 }
 
-void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
                                          GLenum format, GLsizei imageSize, const GLvoid* data)
 {
     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
@@ -831,7 +842,12 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs
           case GL_TEXTURE_2D:
             {
                 gl::Texture2D *texture = context->getTexture2D();
-                texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
+                gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, context->getState().getUnpackState(), data);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -843,7 +859,12 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs
           case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
             {
                 gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+                gl::Error error = texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, context->getState().getUnpackState(), data);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -854,7 +875,7 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs
     }
 }
 
-void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
 {
     EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
           "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
@@ -884,7 +905,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
           case GL_TEXTURE_2D:
             {
                 gl::Texture2D *texture = context->getTexture2D();
-                texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
+                gl::Error error = texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -896,7 +922,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
           case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
             {
                 gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
+                gl::Error error = texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -907,7 +938,7 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
     }
 }
 
-void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
 {
     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
           "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
@@ -937,7 +968,12 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
           case GL_TEXTURE_2D:
             {
                 gl::Texture2D *texture = context->getTexture2D();
-                texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
+                gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -949,7 +985,12 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
           case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
             {
                 gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
+                gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -960,7 +1001,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
     }
 }
 
-GLuint __stdcall glCreateProgram(void)
+GLuint GL_APIENTRY glCreateProgram(void)
 {
     EVENT("()");
 
@@ -973,7 +1014,7 @@ GLuint __stdcall glCreateProgram(void)
     return 0;
 }
 
-GLuint __stdcall glCreateShader(GLenum type)
+GLuint GL_APIENTRY glCreateShader(GLenum type)
 {
     EVENT("(GLenum type = 0x%X)", type);
 
@@ -995,7 +1036,7 @@ GLuint __stdcall glCreateShader(GLenum type)
     return 0;
 }
 
-void __stdcall glCullFace(GLenum mode)
+void GL_APIENTRY glCullFace(GLenum mode)
 {
     EVENT("(GLenum mode = 0x%X)", mode);
 
@@ -1018,7 +1059,7 @@ void __stdcall glCullFace(GLenum mode)
     }
 }
 
-void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers)
+void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers)
 {
     EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
 
@@ -1038,7 +1079,7 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers)
     }
 }
 
-void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences)
+void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences)
 {
     EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
 
@@ -1058,7 +1099,7 @@ void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences)
     }
 }
 
-void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
+void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
 {
     EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
 
@@ -1081,7 +1122,7 @@ void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
     }
 }
 
-void __stdcall glDeleteProgram(GLuint program)
+void GL_APIENTRY glDeleteProgram(GLuint program)
 {
     EVENT("(GLuint program = %d)", program);
 
@@ -1111,7 +1152,7 @@ void __stdcall glDeleteProgram(GLuint program)
     }
 }
 
-void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
+void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
 {
     EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
 
@@ -1131,7 +1172,7 @@ void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
     }
 }
 
-void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
+void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
 {
     EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
 
@@ -1151,7 +1192,7 @@ void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
     }
 }
 
-void __stdcall glDeleteShader(GLuint shader)
+void GL_APIENTRY glDeleteShader(GLuint shader)
 {
     EVENT("(GLuint shader = %d)", shader);
 
@@ -1181,7 +1222,7 @@ void __stdcall glDeleteShader(GLuint shader)
     }
 }
 
-void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures)
+void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures)
 {
     EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
 
@@ -1204,7 +1245,7 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures)
     }
 }
 
-void __stdcall glDepthFunc(GLenum func)
+void GL_APIENTRY glDepthFunc(GLenum func)
 {
     EVENT("(GLenum func = 0x%X)", func);
 
@@ -1231,7 +1272,7 @@ void __stdcall glDepthFunc(GLenum func)
     }
 }
 
-void __stdcall glDepthMask(GLboolean flag)
+void GL_APIENTRY glDepthMask(GLboolean flag)
 {
     EVENT("(GLboolean flag = %u)", flag);
 
@@ -1242,7 +1283,7 @@ void __stdcall glDepthMask(GLboolean flag)
     }
 }
 
-void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar)
+void GL_APIENTRY glDepthRangef(GLclampf zNear, GLclampf zFar)
 {
     EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
 
@@ -1253,7 +1294,7 @@ void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar)
     }
 }
 
-void __stdcall glDetachShader(GLuint program, GLuint shader)
+void GL_APIENTRY glDetachShader(GLuint program, GLuint shader)
 {
     EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
 
@@ -1302,7 +1343,7 @@ void __stdcall glDetachShader(GLuint program, GLuint shader)
     }
 }
 
-void __stdcall glDisable(GLenum cap)
+void GL_APIENTRY glDisable(GLenum cap)
 {
     EVENT("(GLenum cap = 0x%X)", cap);
 
@@ -1319,7 +1360,7 @@ void __stdcall glDisable(GLenum cap)
     }
 }
 
-void __stdcall glDisableVertexAttribArray(GLuint index)
+void GL_APIENTRY glDisableVertexAttribArray(GLuint index)
 {
     EVENT("(GLuint index = %d)", index);
 
@@ -1336,7 +1377,7 @@ void __stdcall glDisableVertexAttribArray(GLuint index)
     }
 }
 
-void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
+void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count)
 {
     EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
 
@@ -1357,7 +1398,7 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
     }
 }
 
-void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
 {
     EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount);
 
@@ -1378,7 +1419,7 @@ void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei coun
     }
 }
 
-void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
+void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
 {
     EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
           mode, count, type, indices);
@@ -1401,7 +1442,7 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv
     }
 }
 
-void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount)
+void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount)
 {
     EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)",
           mode, count, type, indices, primcount);
@@ -1424,7 +1465,7 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t
     }
 }
 
-void __stdcall glEnable(GLenum cap)
+void GL_APIENTRY glEnable(GLenum cap)
 {
     EVENT("(GLenum cap = 0x%X)", cap);
 
@@ -1441,7 +1482,7 @@ void __stdcall glEnable(GLenum cap)
     }
 }
 
-void __stdcall glEnableVertexAttribArray(GLuint index)
+void GL_APIENTRY glEnableVertexAttribArray(GLuint index)
 {
     EVENT("(GLuint index = %d)", index);
 
@@ -1458,7 +1499,7 @@ void __stdcall glEnableVertexAttribArray(GLuint index)
     }
 }
 
-void __stdcall glEndQueryEXT(GLenum target)
+void GL_APIENTRY glEndQueryEXT(GLenum target)
 {
     EVENT("GLenum target = 0x%X)", target);
 
@@ -1479,7 +1520,7 @@ void __stdcall glEndQueryEXT(GLenum target)
     }
 }
 
-void __stdcall glFinishFenceNV(GLuint fence)
+void GL_APIENTRY glFinishFenceNV(GLuint fence)
 {
     EVENT("(GLuint fence = %d)", fence);
 
@@ -1504,29 +1545,39 @@ void __stdcall glFinishFenceNV(GLuint fence)
     }
 }
 
-void __stdcall glFinish(void)
+void GL_APIENTRY glFinish(void)
 {
     EVENT("()");
 
     gl::Context *context = gl::getNonLostContext();
     if (context)
     {
-        context->sync(true);
+        gl::Error error = context->sync(true);
+        if (error.isError())
+        {
+            context->recordError(error);
+            return;
+        }
     }
 }
 
-void __stdcall glFlush(void)
+void GL_APIENTRY glFlush(void)
 {
     EVENT("()");
 
     gl::Context *context = gl::getNonLostContext();
     if (context)
     {
-        context->sync(false);
+        gl::Error error = context->sync(false);
+        if (error.isError())
+        {
+            context->recordError(error);
+            return;
+        }
     }
 }
 
-void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+void GL_APIENTRY glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
 {
     EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
           "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
@@ -1548,33 +1599,19 @@ void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenu
         gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
         ASSERT(framebuffer);
 
-        if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+        if (renderbuffer != 0)
         {
-            unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
-            framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer, 0, 0);
+            gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
+            framebuffer->setRenderbufferAttachment(attachment, renderbufferObject);
         }
         else
         {
-            switch (attachment)
-            {
-              case GL_DEPTH_ATTACHMENT:
-                framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0);
-                break;
-              case GL_STENCIL_ATTACHMENT:
-                framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0);
-                break;
-              case GL_DEPTH_STENCIL_ATTACHMENT:
-                framebuffer->setDepthStencilBuffer(GL_RENDERBUFFER, renderbuffer, 0, 0);
-                break;
-              default:
-                UNREACHABLE();
-                break;
-            }
+            framebuffer->setNULLAttachment(attachment);
         }
     }
 }
 
-void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
 {
     EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
           "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
@@ -1587,31 +1624,23 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t
             return;
         }
 
-        if (texture == 0)
-        {
-            textarget = GL_NONE;
-        }
-
         gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+        ASSERT(framebuffer);
 
-        if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+        if (texture != 0)
         {
-            const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
-            framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, 0);
+            gl::Texture *textureObj = context->getTexture(texture);
+            gl::ImageIndex index(textarget, level, gl::ImageIndex::ENTIRE_LEVEL);
+            framebuffer->setTextureAttachment(attachment, textureObj, index);
         }
         else
         {
-            switch (attachment)
-            {
-              case GL_DEPTH_ATTACHMENT:         framebuffer->setDepthbuffer(textarget, texture, level, 0);        break;
-              case GL_STENCIL_ATTACHMENT:       framebuffer->setStencilbuffer(textarget, texture, level, 0);      break;
-              case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, 0); break;
-            }
+            framebuffer->setNULLAttachment(attachment);
         }
     }
 }
 
-void __stdcall glFrontFace(GLenum mode)
+void GL_APIENTRY glFrontFace(GLenum mode)
 {
     EVENT("(GLenum mode = 0x%X)", mode);
 
@@ -1631,7 +1660,7 @@ void __stdcall glFrontFace(GLenum mode)
     }
 }
 
-void __stdcall glGenBuffers(GLsizei n, GLuint* buffers)
+void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers)
 {
     EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
 
@@ -1651,7 +1680,7 @@ void __stdcall glGenBuffers(GLsizei n, GLuint* buffers)
     }
 }
 
-void __stdcall glGenerateMipmap(GLenum target)
+void GL_APIENTRY glGenerateMipmap(GLenum target)
 {
     EVENT("(GLenum target = 0x%X)", target);
 
@@ -1721,11 +1750,16 @@ void __stdcall glGenerateMipmap(GLenum target)
             }
         }
 
-        texture->generateMipmaps();
+        gl::Error error = texture->generateMipmaps();
+        if (error.isError())
+        {
+            context->recordError(error);
+            return;
+        }
     }
 }
 
-void __stdcall glGenFencesNV(GLsizei n, GLuint* fences)
+void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences)
 {
     EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
 
@@ -1745,7 +1779,7 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences)
     }
 }
 
-void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers)
+void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint* framebuffers)
 {
     EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
 
@@ -1765,7 +1799,7 @@ void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers)
     }
 }
 
-void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids)
+void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint* ids)
 {
     EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
 
@@ -1785,7 +1819,7 @@ void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids)
     }
 }
 
-void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
 {
     EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
 
@@ -1805,7 +1839,7 @@ void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
     }
 }
 
-void __stdcall glGenTextures(GLsizei n, GLuint* textures)
+void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures)
 {
     EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
 
@@ -1825,7 +1859,7 @@ void __stdcall glGenTextures(GLsizei n, GLuint* textures)
     }
 }
 
-void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
 {
     EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
           "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
@@ -1866,7 +1900,7 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize,
     }
 }
 
-void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+void GL_APIENTRY glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
 {
     EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
           "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
@@ -1908,7 +1942,7 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize,
     }
 }
 
-void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+void GL_APIENTRY glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
 {
     EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
           program, maxcount, count, shaders);
@@ -1942,7 +1976,7 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c
     }
 }
 
-GLint __stdcall glGetAttribLocation(GLuint program, const GLchar* name)
+GLint GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar* name)
 {
     EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name);
 
@@ -1978,7 +2012,7 @@ GLint __stdcall glGetAttribLocation(GLuint program, const GLchar* name)
     return -1;
 }
 
-void __stdcall glGetBooleanv(GLenum pname, GLboolean* params)
+void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params)
 {
     EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)",  pname, params);
 
@@ -2003,7 +2037,7 @@ void __stdcall glGetBooleanv(GLenum pname, GLboolean* params)
     }
 }
 
-void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
+void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
 {
     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
 
@@ -2056,7 +2090,7 @@ void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params
     }
 }
 
-GLenum __stdcall glGetError(void)
+GLenum GL_APIENTRY glGetError(void)
 {
     EVENT("()");
 
@@ -2070,7 +2104,7 @@ GLenum __stdcall glGetError(void)
     return GL_NO_ERROR;
 }
 
-void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
+void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
 {
     EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
 
@@ -2094,19 +2128,40 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
         switch (pname)
         {
           case GL_FENCE_STATUS_NV:
+            {
+                // GL_NV_fence spec:
+                // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
+                // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
+                GLboolean status = GL_TRUE;
+                if (fenceObject->getStatus() != GL_TRUE)
+                {
+                    gl::Error error = fenceObject->testFence(&status);
+                    if (error.isError())
+                    {
+                        context->recordError(error);
+                        return;
+                    }
+                }
+                *params = status;
+                break;
+            }
+
           case GL_FENCE_CONDITION_NV:
-            break;
+            {
+                *params = fenceObject->getCondition();
+                break;
+            }
 
           default:
-            context->recordError(gl::Error(GL_INVALID_ENUM));
-            return;
+            {
+                context->recordError(gl::Error(GL_INVALID_ENUM));
+                return;
+            }
         }
-
-        params[0] = fenceObject->getFencei(pname);
     }
 }
 
-void __stdcall glGetFloatv(GLenum pname, GLfloat* params)
+void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params)
 {
     EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
 
@@ -2131,7 +2186,7 @@ void __stdcall glGetFloatv(GLenum pname, GLfloat* params)
     }
 }
 
-void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
 {
     EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
           target, attachment, pname, params);
@@ -2214,6 +2269,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac
 
         GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id();
         gl::Framebuffer *framebuffer = context->getFramebuffer(framebufferHandle);
+        ASSERT(framebuffer);
 
         if (framebufferHandle == 0)
         {
@@ -2428,7 +2484,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac
     }
 }
 
-GLenum __stdcall glGetGraphicsResetStatusEXT(void)
+GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void)
 {
     EVENT("()");
 
@@ -2442,7 +2498,7 @@ GLenum __stdcall glGetGraphicsResetStatusEXT(void)
     return GL_NO_ERROR;
 }
 
-void __stdcall glGetIntegerv(GLenum pname, GLint* params)
+void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params)
 {
     EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
 
@@ -2468,7 +2524,7 @@ void __stdcall glGetIntegerv(GLenum pname, GLint* params)
     }
 }
 
-void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params)
+void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint* params)
 {
     EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);
 
@@ -2552,7 +2608,7 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params)
     }
 }
 
-void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
 {
     EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
           program, bufsize, length, infolog);
@@ -2578,7 +2634,7 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len
     }
 }
 
-void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
+void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
 {
     EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params);
 
@@ -2604,7 +2660,7 @@ void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
     }
 }
 
-void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
+void GL_APIENTRY glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
 {
     EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
 
@@ -2656,7 +2712,7 @@ void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
     }
 }
 
-void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
+void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
 {
     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
 
@@ -2705,7 +2761,7 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint*
     }
 }
 
-void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
+void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
 {
     EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
 
@@ -2748,7 +2804,7 @@ void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
     }
 }
 
-void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
 {
     EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
           shader, bufsize, length, infolog);
@@ -2774,7 +2830,7 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt
     }
 }
 
-void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
 {
     EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
           shadertype, precisiontype, range, precision);
@@ -2821,7 +2877,7 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp
     }
 }
 
-void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
 {
     EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
           shader, bufsize, length, source);
@@ -2847,7 +2903,7 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length
     }
 }
 
-void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+void GL_APIENTRY glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
 {
     EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
           shader, bufsize, length, source);
@@ -2869,11 +2925,12 @@ void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize,
             return;
         }
 
-        shaderObject->getTranslatedSource(bufsize, length, source);
+        // Only returns extra info if ANGLE_GENERATE_SHADER_DEBUG_INFO is defined
+        shaderObject->getTranslatedSourceWithDebugInfo(bufsize, length, source);
     }
 }
 
-const GLubyte* __stdcall glGetString(GLenum name)
+const GLubyte* GL_APIENTRY glGetString(GLenum name)
 {
     EVENT("(GLenum name = 0x%X)", name);
 
@@ -2919,7 +2976,7 @@ const GLubyte* __stdcall glGetString(GLenum name)
     }
 }
 
-void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
+void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
 {
     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
 
@@ -3051,7 +3108,7 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
     }
 }
 
-void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
+void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
 {
     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
 
@@ -3098,7 +3155,7 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
                 context->recordError(gl::Error(GL_INVALID_ENUM));
                 return;
             }
-            *params = texture->immutableLevelCount();
+            *params = static_cast<GLint>(texture->immutableLevelCount());
             break;
           case GL_TEXTURE_USAGE_ANGLE:
             *params = texture->getUsage();
@@ -3183,7 +3240,7 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
     }
 }
 
-void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
 {
     EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",
           program, location, bufSize, params);
@@ -3205,7 +3262,7 @@ void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSiz
     }
 }
 
-void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params)
+void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat* params)
 {
     EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
 
@@ -3226,7 +3283,7 @@ void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params)
     }
 }
 
-void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
+void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
 {
     EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
           program, location, bufSize, params);
@@ -3248,7 +3305,7 @@ void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSiz
     }
 }
 
-void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params)
+void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint* params)
 {
     EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
 
@@ -3269,7 +3326,7 @@ void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params)
     }
 }
 
-GLint __stdcall glGetUniformLocation(GLuint program, const GLchar* name)
+GLint GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar* name)
 {
     EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);
 
@@ -3310,7 +3367,7 @@ GLint __stdcall glGetUniformLocation(GLuint program, const GLchar* name)
     return -1;
 }
 
-void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
+void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
 {
     EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
 
@@ -3344,7 +3401,7 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
     }
 }
 
-void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
+void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
 {
     EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
 
@@ -3380,7 +3437,7 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
     }
 }
 
-void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
+void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
 {
     EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
 
@@ -3403,7 +3460,7 @@ void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** po
     }
 }
 
-void __stdcall glHint(GLenum target, GLenum mode)
+void GL_APIENTRY glHint(GLenum target, GLenum mode)
 {
     EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
 
@@ -3439,7 +3496,7 @@ void __stdcall glHint(GLenum target, GLenum mode)
     }
 }
 
-GLboolean __stdcall glIsBuffer(GLuint buffer)
+GLboolean GL_APIENTRY glIsBuffer(GLuint buffer)
 {
     EVENT("(GLuint buffer = %d)", buffer);
 
@@ -3457,7 +3514,7 @@ GLboolean __stdcall glIsBuffer(GLuint buffer)
     return GL_FALSE;
 }
 
-GLboolean __stdcall glIsEnabled(GLenum cap)
+GLboolean GL_APIENTRY glIsEnabled(GLenum cap)
 {
     EVENT("(GLenum cap = 0x%X)", cap);
 
@@ -3476,7 +3533,7 @@ GLboolean __stdcall glIsEnabled(GLenum cap)
     return false;
 }
 
-GLboolean __stdcall glIsFenceNV(GLuint fence)
+GLboolean GL_APIENTRY glIsFenceNV(GLuint fence)
 {
     EVENT("(GLuint fence = %d)", fence);
 
@@ -3496,7 +3553,7 @@ GLboolean __stdcall glIsFenceNV(GLuint fence)
     return GL_FALSE;
 }
 
-GLboolean __stdcall glIsFramebuffer(GLuint framebuffer)
+GLboolean GL_APIENTRY glIsFramebuffer(GLuint framebuffer)
 {
     EVENT("(GLuint framebuffer = %d)", framebuffer);
 
@@ -3514,7 +3571,7 @@ GLboolean __stdcall glIsFramebuffer(GLuint framebuffer)
     return GL_FALSE;
 }
 
-GLboolean __stdcall glIsProgram(GLuint program)
+GLboolean GL_APIENTRY glIsProgram(GLuint program)
 {
     EVENT("(GLuint program = %d)", program);
 
@@ -3532,7 +3589,7 @@ GLboolean __stdcall glIsProgram(GLuint program)
     return GL_FALSE;
 }
 
-GLboolean __stdcall glIsQueryEXT(GLuint id)
+GLboolean GL_APIENTRY glIsQueryEXT(GLuint id)
 {
     EVENT("(GLuint id = %d)", id);
 
@@ -3545,7 +3602,7 @@ GLboolean __stdcall glIsQueryEXT(GLuint id)
     return GL_FALSE;
 }
 
-GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer)
+GLboolean GL_APIENTRY glIsRenderbuffer(GLuint renderbuffer)
 {
     EVENT("(GLuint renderbuffer = %d)", renderbuffer);
 
@@ -3563,7 +3620,7 @@ GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer)
     return GL_FALSE;
 }
 
-GLboolean __stdcall glIsShader(GLuint shader)
+GLboolean GL_APIENTRY glIsShader(GLuint shader)
 {
     EVENT("(GLuint shader = %d)", shader);
 
@@ -3581,7 +3638,7 @@ GLboolean __stdcall glIsShader(GLuint shader)
     return GL_FALSE;
 }
 
-GLboolean __stdcall glIsTexture(GLuint texture)
+GLboolean GL_APIENTRY glIsTexture(GLuint texture)
 {
     EVENT("(GLuint texture = %d)", texture);
 
@@ -3599,7 +3656,7 @@ GLboolean __stdcall glIsTexture(GLuint texture)
     return GL_FALSE;
 }
 
-void __stdcall glLineWidth(GLfloat width)
+void GL_APIENTRY glLineWidth(GLfloat width)
 {
     EVENT("(GLfloat width = %f)", width);
 
@@ -3616,7 +3673,7 @@ void __stdcall glLineWidth(GLfloat width)
     }
 }
 
-void __stdcall glLinkProgram(GLuint program)
+void GL_APIENTRY glLinkProgram(GLuint program)
 {
     EVENT("(GLuint program = %d)", program);
 
@@ -3639,11 +3696,16 @@ void __stdcall glLinkProgram(GLuint program)
             }
         }
 
-        context->linkProgram(program);
+        gl::Error error = context->linkProgram(program);
+        if (error.isError())
+        {
+            context->recordError(error);
+            return;
+        }
     }
 }
 
-void __stdcall glPixelStorei(GLenum pname, GLint param)
+void GL_APIENTRY glPixelStorei(GLenum pname, GLint param)
 {
     EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
 
@@ -3699,7 +3761,7 @@ void __stdcall glPixelStorei(GLenum pname, GLint param)
     }
 }
 
-void __stdcall glPolygonOffset(GLfloat factor, GLfloat units)
+void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units)
 {
     EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
 
@@ -3710,7 +3772,7 @@ void __stdcall glPolygonOffset(GLfloat factor, GLfloat units)
     }
 }
 
-void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
+void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
                                 GLenum format, GLenum type, GLsizei bufSize,
                                 GLvoid *data)
 {
@@ -3742,7 +3804,7 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
     }
 }
 
-void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
                             GLenum format, GLenum type, GLvoid* pixels)
 {
     EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
@@ -3773,7 +3835,7 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
     }
 }
 
-void __stdcall glReleaseShaderCompiler(void)
+void GL_APIENTRY glReleaseShaderCompiler(void)
 {
     EVENT("()");
 
@@ -3785,7 +3847,7 @@ void __stdcall glReleaseShaderCompiler(void)
     }
 }
 
-void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
 {
     EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
           target, samples, internalformat, width, height);
@@ -3799,16 +3861,22 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp
             return;
         }
 
-        context->setRenderbufferStorage(width, height, internalformat, samples);
+        gl::Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
+        gl::Error error = renderbuffer->setStorage(width, height, internalformat, samples);
+        if (error.isError())
+        {
+            context->recordError(error);
+            return;
+        }
     }
 }
 
-void __stdcall glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
 {
     glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height);
 }
 
-void __stdcall glSampleCoverage(GLclampf value, GLboolean invert)
+void GL_APIENTRY glSampleCoverage(GLclampf value, GLboolean invert)
 {
     EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert);
 
@@ -3820,7 +3888,7 @@ void __stdcall glSampleCoverage(GLclampf value, GLboolean invert)
     }
 }
 
-void __stdcall glSetFenceNV(GLuint fence, GLenum condition)
+void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition)
 {
     EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
 
@@ -3841,11 +3909,16 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition)
             return;
         }
 
-        fenceObject->setFence(condition);
+        gl::Error error = fenceObject->setFence(condition);
+        if (error.isError())
+        {
+            context->recordError(error);
+            return;
+        }
     }
 }
 
-void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
+void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
 {
     EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
 
@@ -3862,7 +3935,7 @@ void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
     }
 }
 
-void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
+void GL_APIENTRY glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
 {
     EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
           "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
@@ -3883,7 +3956,7 @@ void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryfor
     }
 }
 
-void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length)
+void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length)
 {
     EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
           shader, count, string, length);
@@ -3917,12 +3990,12 @@ void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar* const*
     }
 }
 
-void __stdcall glStencilFunc(GLenum func, GLint ref, GLuint mask)
+void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask)
 {
     glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
 }
 
-void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+void GL_APIENTRY glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
 {
     EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
 
@@ -3970,12 +4043,12 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint
     }
 }
 
-void __stdcall glStencilMask(GLuint mask)
+void GL_APIENTRY glStencilMask(GLuint mask)
 {
     glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
 }
 
-void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask)
+void GL_APIENTRY glStencilMaskSeparate(GLenum face, GLuint mask)
 {
     EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
 
@@ -4006,12 +4079,12 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask)
     }
 }
 
-void __stdcall glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
 {
     glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
 }
 
-void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+void GL_APIENTRY glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
 {
     EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
           face, fail, zfail, zpass);
@@ -4094,7 +4167,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu
     }
 }
 
-GLboolean __stdcall glTestFenceNV(GLuint fence)
+GLboolean GL_APIENTRY glTestFenceNV(GLuint fence)
 {
     EVENT("(GLuint fence = %d)", fence);
 
@@ -4115,13 +4188,21 @@ GLboolean __stdcall glTestFenceNV(GLuint fence)
             return GL_TRUE;
         }
 
-        return fenceObject->testFence();
+        GLboolean result;
+        gl::Error error = fenceObject->testFence(&result);
+        if (error.isError())
+        {
+            context->recordError(error);
+            return GL_TRUE;
+        }
+
+        return result;
     }
 
     return GL_TRUE;
 }
 
-void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
+void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
                             GLint border, GLenum format, GLenum type, const GLvoid* pixels)
 {
     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
@@ -4150,51 +4231,38 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
           case GL_TEXTURE_2D:
             {
                 gl::Texture2D *texture = context->getTexture2D();
-                texture->setImage(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
+                gl::Error error = texture->setImage(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
+
           case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-            {
-                gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                texture->setImagePosX(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
-            }
-            break;
           case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-            {
-                gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                texture->setImageNegX(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
-            }
-            break;
           case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-            {
-                gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                texture->setImagePosY(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
-            }
-            break;
           case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-            {
-                gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                texture->setImageNegY(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
-            }
-            break;
           case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-            {
-                gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                texture->setImagePosZ(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
-            }
-            break;
           case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
             {
                 gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                texture->setImageNegZ(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
+                gl::Error error = texture->setImage(target, level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
+
           default: UNREACHABLE();
         }
     }
 }
 
-void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param)
+void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param)
 {
     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param);
 
@@ -4238,12 +4306,12 @@ void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param)
     }
 }
 
-void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
 {
     glTexParameterf(target, pname, (GLfloat)*params);
 }
 
-void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param)
+void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
 {
     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
 
@@ -4287,12 +4355,12 @@ void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param)
     }
 }
 
-void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
+void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
 {
     glTexParameteri(target, pname, *params);
 }
 
-void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
 {
     EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
            target, levels, internalformat, width, height);
@@ -4323,14 +4391,24 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf
           case GL_TEXTURE_2D:
             {
                 gl::Texture2D *texture2d = context->getTexture2D();
-                texture2d->storage(levels, internalformat, width, height);
+                gl::Error error = texture2d->storage(levels, internalformat, width, height);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
           case GL_TEXTURE_CUBE_MAP:
             {
                 gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
-                textureCube->storage(levels, internalformat, width);
+                gl::Error error = textureCube->storage(levels, internalformat, width);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -4341,7 +4419,7 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf
     }
 }
 
-void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
                                GLenum format, GLenum type, const GLvoid* pixels)
 {
     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
@@ -4377,7 +4455,12 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint
           case GL_TEXTURE_2D:
             {
                 gl::Texture2D *texture = context->getTexture2D();
-                texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels);
+                gl::Error error = texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -4389,7 +4472,12 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint
           case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
             {
                 gl::TextureCubeMap *texture = context->getTextureCubeMap();
-                texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels);
+                gl::Error error = texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -4399,12 +4487,12 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint
     }
 }
 
-void __stdcall glUniform1f(GLint location, GLfloat x)
+void GL_APIENTRY glUniform1f(GLint location, GLfloat x)
 {
     glUniform1fv(location, 1, &x);
 }
 
-void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
 
@@ -4421,12 +4509,12 @@ void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
     }
 }
 
-void __stdcall glUniform1i(GLint location, GLint x)
+void GL_APIENTRY glUniform1i(GLint location, GLint x)
 {
     glUniform1iv(location, 1, &x);
 }
 
-void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v)
+void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint* v)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
 
@@ -4443,14 +4531,14 @@ void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v)
     }
 }
 
-void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y)
+void GL_APIENTRY glUniform2f(GLint location, GLfloat x, GLfloat y)
 {
     GLfloat xy[2] = {x, y};
 
     glUniform2fv(location, 1, xy);
 }
 
-void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
+void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
 
@@ -4467,14 +4555,14 @@ void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
     }
 }
 
-void __stdcall glUniform2i(GLint location, GLint x, GLint y)
+void GL_APIENTRY glUniform2i(GLint location, GLint x, GLint y)
 {
     GLint xy[2] = {x, y};
 
     glUniform2iv(location, 1, xy);
 }
 
-void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v)
+void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint* v)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
 
@@ -4491,14 +4579,14 @@ void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v)
     }
 }
 
-void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+void GL_APIENTRY glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
 {
     GLfloat xyz[3] = {x, y, z};
 
     glUniform3fv(location, 1, xyz);
 }
 
-void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
+void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
 
@@ -4515,14 +4603,14 @@ void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
     }
 }
 
-void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z)
+void GL_APIENTRY glUniform3i(GLint location, GLint x, GLint y, GLint z)
 {
     GLint xyz[3] = {x, y, z};
 
     glUniform3iv(location, 1, xyz);
 }
 
-void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v)
+void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint* v)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
 
@@ -4539,14 +4627,14 @@ void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v)
     }
 }
 
-void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+void GL_APIENTRY glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 {
     GLfloat xyzw[4] = {x, y, z, w};
 
     glUniform4fv(location, 1, xyzw);
 }
 
-void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
+void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
 
@@ -4563,14 +4651,14 @@ void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
     }
 }
 
-void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+void GL_APIENTRY glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
 {
     GLint xyzw[4] = {x, y, z, w};
 
     glUniform4iv(location, 1, xyzw);
 }
 
-void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v)
+void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint* v)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
 
@@ -4587,7 +4675,7 @@ void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v)
     }
 }
 
-void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
           location, count, transpose, value);
@@ -4605,7 +4693,7 @@ void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean trans
     }
 }
 
-void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
           location, count, transpose, value);
@@ -4623,7 +4711,7 @@ void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean trans
     }
 }
 
-void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
           location, count, transpose, value);
@@ -4641,7 +4729,7 @@ void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean trans
     }
 }
 
-void __stdcall glUseProgram(GLuint program)
+void GL_APIENTRY glUseProgram(GLuint program)
 {
     EVENT("(GLuint program = %d)", program);
 
@@ -4674,7 +4762,7 @@ void __stdcall glUseProgram(GLuint program)
     }
 }
 
-void __stdcall glValidateProgram(GLuint program)
+void GL_APIENTRY glValidateProgram(GLuint program)
 {
     EVENT("(GLuint program = %d)", program);
 
@@ -4701,7 +4789,7 @@ void __stdcall glValidateProgram(GLuint program)
     }
 }
 
-void __stdcall glVertexAttrib1f(GLuint index, GLfloat x)
+void GL_APIENTRY glVertexAttrib1f(GLuint index, GLfloat x)
 {
     EVENT("(GLuint index = %d, GLfloat x = %f)", index, x);
 
@@ -4719,7 +4807,7 @@ void __stdcall glVertexAttrib1f(GLuint index, GLfloat x)
     }
 }
 
-void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values)
+void GL_APIENTRY glVertexAttrib1fv(GLuint index, const GLfloat* values)
 {
     EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
 
@@ -4737,7 +4825,7 @@ void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values)
     }
 }
 
-void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+void GL_APIENTRY glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
 {
     EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
 
@@ -4755,7 +4843,7 @@ void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
     }
 }
 
-void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values)
+void GL_APIENTRY glVertexAttrib2fv(GLuint index, const GLfloat* values)
 {
     EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
 
@@ -4773,7 +4861,7 @@ void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values)
     }
 }
 
-void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+void GL_APIENTRY glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
 {
     EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
 
@@ -4791,7 +4879,7 @@ void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
     }
 }
 
-void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values)
+void GL_APIENTRY glVertexAttrib3fv(GLuint index, const GLfloat* values)
 {
     EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
 
@@ -4809,7 +4897,7 @@ void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values)
     }
 }
 
-void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+void GL_APIENTRY glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 {
     EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
 
@@ -4827,7 +4915,7 @@ void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, G
     }
 }
 
-void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values)
+void GL_APIENTRY glVertexAttrib4fv(GLuint index, const GLfloat* values)
 {
     EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
 
@@ -4844,7 +4932,7 @@ void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values)
     }
 }
 
-void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
+void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
 {
     EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
 
@@ -4861,7 +4949,7 @@ void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
     }
 }
 
-void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+void GL_APIENTRY glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
 {
     EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
           "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
@@ -4936,7 +5024,7 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo
     }
 }
 
-void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
+void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
 {
     EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
 
@@ -4955,7 +5043,7 @@ void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
 
 // OpenGL ES 3.0 functions
 
-void __stdcall glReadBuffer(GLenum mode)
+void GL_APIENTRY glReadBuffer(GLenum mode)
 {
     EVENT("(GLenum mode = 0x%X)", mode);
 
@@ -4973,7 +5061,7 @@ void __stdcall glReadBuffer(GLenum mode)
     }
 }
 
-void __stdcall glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices)
+void GL_APIENTRY glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices)
 {
     EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, "
           "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices);
@@ -4992,7 +5080,7 @@ void __stdcall glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsize
     }
 }
 
-void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
 {
     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
           "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, "
@@ -5020,14 +5108,24 @@ void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GL
           case GL_TEXTURE_3D:
             {
                 gl::Texture3D *texture = context->getTexture3D();
-                texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels);
+                gl::Error error = texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
           case GL_TEXTURE_2D_ARRAY:
             {
                 gl::Texture2DArray *texture = context->getTexture2DArray();
-                texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels);
+                gl::Error error = texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -5038,7 +5136,7 @@ void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GL
     }
 }
 
-void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
+void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
 {
     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
           "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
@@ -5073,14 +5171,24 @@ void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint
           case GL_TEXTURE_3D:
             {
                 gl::Texture3D *texture = context->getTexture3D();
-                texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels);
+                gl::Error error = texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
           case GL_TEXTURE_2D_ARRAY:
             {
                 gl::Texture2DArray *texture = context->getTexture2DArray();
-                texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels);
+                gl::Error error = texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -5091,7 +5199,7 @@ void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint
     }
 }
 
-void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+void GL_APIENTRY glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
 {
     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
           "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
@@ -5129,11 +5237,16 @@ void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GL
             return;
         }
 
-        texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
+        gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
+        if (error.isError())
+        {
+            context->recordError(error);
+            return;
+        }
     }
 }
 
-void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
+void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
 {
     EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
           "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
@@ -5168,14 +5281,24 @@ void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum interna
           case GL_TEXTURE_3D:
             {
                 gl::Texture3D *texture = context->getTexture3D();
-                texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
+                gl::Error error = texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, context->getState().getUnpackState(), data);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
           case GL_TEXTURE_2D_ARRAY:
             {
                 gl::Texture2DArray *texture = context->getTexture2DArray();
-                texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
+                gl::Error error = texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, context->getState().getUnpackState(), data);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -5186,7 +5309,7 @@ void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum interna
     }
 }
 
-void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
+void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
 {
     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
         "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
@@ -5233,16 +5356,26 @@ void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffs
           case GL_TEXTURE_3D:
             {
                 gl::Texture3D *texture = context->getTexture3D();
-                texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth,
-                                            format, imageSize, data);
+                gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth,
+                                                              format, imageSize, context->getState().getUnpackState(), data);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
           case GL_TEXTURE_2D_ARRAY:
             {
                 gl::Texture2DArray *texture = context->getTexture2DArray();
-                texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth,
-                                            format, imageSize, data);
+                gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth,
+                                                              format, imageSize, context->getState().getUnpackState(), data);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -5253,7 +5386,7 @@ void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffs
     }
 }
 
-void __stdcall glGenQueries(GLsizei n, GLuint* ids)
+void GL_APIENTRY glGenQueries(GLsizei n, GLuint* ids)
 {
     EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
 
@@ -5279,7 +5412,7 @@ void __stdcall glGenQueries(GLsizei n, GLuint* ids)
     }
 }
 
-void __stdcall glDeleteQueries(GLsizei n, const GLuint* ids)
+void GL_APIENTRY glDeleteQueries(GLsizei n, const GLuint* ids)
 {
     EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
 
@@ -5305,7 +5438,7 @@ void __stdcall glDeleteQueries(GLsizei n, const GLuint* ids)
     }
 }
 
-GLboolean __stdcall glIsQuery(GLuint id)
+GLboolean GL_APIENTRY glIsQuery(GLuint id)
 {
     EVENT("(GLuint id = %u)", id);
 
@@ -5324,7 +5457,7 @@ GLboolean __stdcall glIsQuery(GLuint id)
     return GL_FALSE;
 }
 
-void __stdcall glBeginQuery(GLenum target, GLuint id)
+void GL_APIENTRY glBeginQuery(GLenum target, GLuint id)
 {
     EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
 
@@ -5351,7 +5484,7 @@ void __stdcall glBeginQuery(GLenum target, GLuint id)
     }
 }
 
-void __stdcall glEndQuery(GLenum target)
+void GL_APIENTRY glEndQuery(GLenum target)
 {
     EVENT("(GLenum target = 0x%X)", target);
 
@@ -5378,7 +5511,7 @@ void __stdcall glEndQuery(GLenum target)
     }
 }
 
-void __stdcall glGetQueryiv(GLenum target, GLenum pname, GLint* params)
+void GL_APIENTRY glGetQueryiv(GLenum target, GLenum pname, GLint* params)
 {
     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
 
@@ -5410,7 +5543,7 @@ void __stdcall glGetQueryiv(GLenum target, GLenum pname, GLint* params)
     }
 }
 
-void __stdcall glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
+void GL_APIENTRY glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
 {
     EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params);
 
@@ -5468,7 +5601,7 @@ void __stdcall glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
     }
 }
 
-GLboolean __stdcall glUnmapBuffer(GLenum target)
+GLboolean GL_APIENTRY glUnmapBuffer(GLenum target)
 {
     EVENT("(GLenum target = 0x%X)", target);
 
@@ -5487,7 +5620,7 @@ GLboolean __stdcall glUnmapBuffer(GLenum target)
     return GL_FALSE;
 }
 
-void __stdcall glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
+void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
 {
     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
 
@@ -5504,7 +5637,7 @@ void __stdcall glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
     }
 }
 
-void __stdcall glDrawBuffers(GLsizei n, const GLenum* bufs)
+void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum* bufs)
 {
     gl::Context *context = gl::getNonLostContext();
     if (context)
@@ -5519,7 +5652,7 @@ void __stdcall glDrawBuffers(GLsizei n, const GLenum* bufs)
     }
 }
 
-void __stdcall glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
           location, count, transpose, value);
@@ -5537,7 +5670,7 @@ void __stdcall glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean tra
     }
 }
 
-void __stdcall glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
           location, count, transpose, value);
@@ -5555,7 +5688,7 @@ void __stdcall glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean tra
     }
 }
 
-void __stdcall glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
           location, count, transpose, value);
@@ -5573,7 +5706,7 @@ void __stdcall glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean tra
     }
 }
 
-void __stdcall glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
           location, count, transpose, value);
@@ -5591,7 +5724,7 @@ void __stdcall glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean tra
     }
 }
 
-void __stdcall glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
           location, count, transpose, value);
@@ -5609,7 +5742,7 @@ void __stdcall glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean tra
     }
 }
 
-void __stdcall glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
           location, count, transpose, value);
@@ -5627,7 +5760,7 @@ void __stdcall glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean tra
     }
 }
 
-void __stdcall glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+void GL_APIENTRY glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
 {
     EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, "
           "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
@@ -5649,12 +5782,17 @@ void __stdcall glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint sr
             return;
         }
 
-        context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
-                                 mask, filter);
+        gl::Error error = context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
+                                                   mask, filter);
+        if (error.isError())
+        {
+            context->recordError(error);
+            return;
+        }
     }
 }
 
-void __stdcall glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
 {
     EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
         target, samples, internalformat, width, height);
@@ -5674,11 +5812,12 @@ void __stdcall glRenderbufferStorageMultisample(GLenum target, GLsizei samples,
             return;
         }
 
-        context->setRenderbufferStorage(width, height, internalformat, samples);
+        gl::Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
+        renderbuffer->setStorage(width, height, internalformat, samples);
     }
 }
 
-void __stdcall glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
 {
     EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)",
         target, attachment, texture, level, layer);
@@ -5695,27 +5834,20 @@ void __stdcall glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuin
         gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
         ASSERT(framebuffer);
 
-        gl::Texture *textureObject = context->getTexture(texture);
-        GLenum textarget = textureObject ? textureObject->getTarget() : GL_NONE;
-
-        if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+        if (texture != 0)
         {
-            const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
-            framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, layer);
+            gl::Texture *textureObject = context->getTexture(texture);
+            gl::ImageIndex index(textureObject->getTarget(), level, layer);
+            framebuffer->setTextureAttachment(attachment, textureObject, index);
         }
         else
         {
-            switch (attachment)
-            {
-              case GL_DEPTH_ATTACHMENT:         framebuffer->setDepthbuffer(textarget, texture, level, layer);        break;
-              case GL_STENCIL_ATTACHMENT:       framebuffer->setStencilbuffer(textarget, texture, level, layer);      break;
-              case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, layer); break;
-            }
+            framebuffer->setNULLAttachment(attachment);
         }
     }
 }
 
-GLvoid* __stdcall glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+GLvoid* GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
 {
     EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
           target, offset, length, access);
@@ -5735,7 +5867,7 @@ GLvoid* __stdcall glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr le
     return NULL;
 }
 
-void __stdcall glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
+void GL_APIENTRY glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
 {
     EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
 
@@ -5752,7 +5884,7 @@ void __stdcall glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeip
     }
 }
 
-void __stdcall glBindVertexArray(GLuint array)
+void GL_APIENTRY glBindVertexArray(GLuint array)
 {
     EVENT("(GLuint array = %u)", array);
 
@@ -5779,7 +5911,7 @@ void __stdcall glBindVertexArray(GLuint array)
     }
 }
 
-void __stdcall glDeleteVertexArrays(GLsizei n, const GLuint* arrays)
+void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint* arrays)
 {
     EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays);
 
@@ -5808,7 +5940,7 @@ void __stdcall glDeleteVertexArrays(GLsizei n, const GLuint* arrays)
     }
 }
 
-void __stdcall glGenVertexArrays(GLsizei n, GLuint* arrays)
+void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint* arrays)
 {
     EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays);
 
@@ -5834,7 +5966,7 @@ void __stdcall glGenVertexArrays(GLsizei n, GLuint* arrays)
     }
 }
 
-GLboolean __stdcall glIsVertexArray(GLuint array)
+GLboolean GL_APIENTRY glIsVertexArray(GLuint array)
 {
     EVENT("(GLuint array = %u)", array);
 
@@ -5860,7 +5992,7 @@ GLboolean __stdcall glIsVertexArray(GLuint array)
     return GL_FALSE;
 }
 
-void __stdcall glGetIntegeri_v(GLenum target, GLuint index, GLint* data)
+void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint* data)
 {
     EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)",
           target, index, data);
@@ -5941,7 +6073,7 @@ void __stdcall glGetIntegeri_v(GLenum target, GLuint index, GLint* data)
     }
 }
 
-void __stdcall glBeginTransformFeedback(GLenum primitiveMode)
+void GL_APIENTRY glBeginTransformFeedback(GLenum primitiveMode)
 {
     EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode);
 
@@ -5986,7 +6118,7 @@ void __stdcall glBeginTransformFeedback(GLenum primitiveMode)
     }
 }
 
-void __stdcall glEndTransformFeedback(void)
+void GL_APIENTRY glEndTransformFeedback(void)
 {
     EVENT("(void)");
 
@@ -6012,7 +6144,7 @@ void __stdcall glEndTransformFeedback(void)
     }
 }
 
-void __stdcall glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
+void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
 {
     EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)",
           target, index, buffer, offset, size);
@@ -6090,7 +6222,7 @@ void __stdcall glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLi
     }
 }
 
-void __stdcall glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
+void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
 {
     EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)",
           target, index, buffer);
@@ -6146,7 +6278,7 @@ void __stdcall glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
     }
 }
 
-void __stdcall glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
+void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
 {
     EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)",
           program, count, varyings, bufferMode);
@@ -6195,7 +6327,7 @@ void __stdcall glTransformFeedbackVaryings(GLuint program, GLsizei count, const
     }
 }
 
-void __stdcall glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
+void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
 {
     EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, "
           "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
@@ -6234,7 +6366,7 @@ void __stdcall glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsiz
     }
 }
 
-void __stdcall glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer)
+void GL_APIENTRY glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer)
 {
     EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)",
           index, size, type, stride, pointer);
@@ -6304,7 +6436,7 @@ void __stdcall glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLs
     }
 }
 
-void __stdcall glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
+void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
 {
     EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
           index, pname, params);
@@ -6346,7 +6478,7 @@ void __stdcall glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
     }
 }
 
-void __stdcall glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
+void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
 {
     EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)",
           index, pname, params);
@@ -6388,7 +6520,7 @@ void __stdcall glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
     }
 }
 
-void __stdcall glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
+void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
 {
     EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
           index, x, y, z, w);
@@ -6413,7 +6545,7 @@ void __stdcall glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint
     }
 }
 
-void __stdcall glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
+void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
 {
     EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)",
           index, x, y, z, w);
@@ -6438,7 +6570,7 @@ void __stdcall glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GL
     }
 }
 
-void __stdcall glVertexAttribI4iv(GLuint index, const GLint* v)
+void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint* v)
 {
     EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v);
 
@@ -6461,7 +6593,7 @@ void __stdcall glVertexAttribI4iv(GLuint index, const GLint* v)
     }
 }
 
-void __stdcall glVertexAttribI4uiv(GLuint index, const GLuint* v)
+void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint* v)
 {
     EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v);
 
@@ -6484,7 +6616,7 @@ void __stdcall glVertexAttribI4uiv(GLuint index, const GLuint* v)
     }
 }
 
-void __stdcall glGetUniformuiv(GLuint program, GLint location, GLuint* params)
+void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint* params)
 {
     EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)",
           program, location, params);
@@ -6506,7 +6638,7 @@ void __stdcall glGetUniformuiv(GLuint program, GLint location, GLuint* params)
     }
 }
 
-GLint __stdcall glGetFragDataLocation(GLuint program, const GLchar *name)
+GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const GLchar *name)
 {
     EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)",
           program, name);
@@ -6547,30 +6679,30 @@ GLint __stdcall glGetFragDataLocation(GLuint program, const GLchar *name)
     return 0;
 }
 
-void __stdcall glUniform1ui(GLint location, GLuint v0)
+void GL_APIENTRY glUniform1ui(GLint location, GLuint v0)
 {
     glUniform1uiv(location, 1, &v0);
 }
 
-void __stdcall glUniform2ui(GLint location, GLuint v0, GLuint v1)
+void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1)
 {
     const GLuint xy[] = { v0, v1 };
     glUniform2uiv(location, 1, xy);
 }
 
-void __stdcall glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
+void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
 {
     const GLuint xyz[] = { v0, v1, v2 };
     glUniform3uiv(location, 1, xyz);
 }
 
-void __stdcall glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
 {
     const GLuint xyzw[] = { v0, v1, v2, v3 };
     glUniform4uiv(location, 1, xyzw);
 }
 
-void __stdcall glUniform1uiv(GLint location, GLsizei count, const GLuint* value)
+void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
           location, count, value);
@@ -6588,7 +6720,7 @@ void __stdcall glUniform1uiv(GLint location, GLsizei count, const GLuint* value)
     }
 }
 
-void __stdcall glUniform2uiv(GLint location, GLsizei count, const GLuint* value)
+void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
           location, count, value);
@@ -6606,7 +6738,7 @@ void __stdcall glUniform2uiv(GLint location, GLsizei count, const GLuint* value)
     }
 }
 
-void __stdcall glUniform3uiv(GLint location, GLsizei count, const GLuint* value)
+void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)",
           location, count, value);
@@ -6624,7 +6756,7 @@ void __stdcall glUniform3uiv(GLint location, GLsizei count, const GLuint* value)
     }
 }
 
-void __stdcall glUniform4uiv(GLint location, GLsizei count, const GLuint* value)
+void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint* value)
 {
     EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
           location, count, value);
@@ -6642,7 +6774,7 @@ void __stdcall glUniform4uiv(GLint location, GLsizei count, const GLuint* value)
     }
 }
 
-void __stdcall glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value)
+void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value)
 {
     EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)",
           buffer, drawbuffer, value);
@@ -6687,7 +6819,7 @@ void __stdcall glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* val
     }
 }
 
-void __stdcall glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value)
+void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value)
 {
     EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)",
           buffer, drawbuffer, value);
@@ -6724,7 +6856,7 @@ void __stdcall glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* v
     }
 }
 
-void __stdcall glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)
+void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)
 {
     EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)",
           buffer, drawbuffer, value);
@@ -6769,7 +6901,7 @@ void __stdcall glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* v
     }
 }
 
-void __stdcall glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
 {
     EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)",
           buffer, drawbuffer, depth, stencil);
@@ -6806,7 +6938,7 @@ void __stdcall glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, G
     }
 }
 
-const GLubyte* __stdcall glGetStringi(GLenum name, GLuint index)
+const GLubyte* GL_APIENTRY glGetStringi(GLenum name, GLuint index)
 {
     EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index);
 
@@ -6837,7 +6969,7 @@ const GLubyte* __stdcall glGetStringi(GLenum name, GLuint index)
     return NULL;
 }
 
-void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
+void GL_APIENTRY glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
 {
     EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
           readTarget, writeTarget, readOffset, writeOffset, size);
@@ -6851,7 +6983,7 @@ void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintp
             return;
         }
 
-        if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, readTarget))
+        if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, writeTarget))
         {
             context->recordError(gl::Error(GL_INVALID_ENUM));
             return;
@@ -6881,7 +7013,7 @@ void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintp
             return;
         }
 
-        if (readBuffer == writeBuffer && abs(readOffset - writeOffset) < size)
+        if (readBuffer == writeBuffer && std::abs(readOffset - writeOffset) < size)
         {
             context->recordError(gl::Error(GL_INVALID_VALUE));
             return;
@@ -6900,7 +7032,7 @@ void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintp
     }
 }
 
-void __stdcall glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices)
+void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices)
 {
     EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)",
           program, uniformCount, uniformNames, uniformIndices);
@@ -6954,7 +7086,7 @@ void __stdcall glGetUniformIndices(GLuint program, GLsizei uniformCount, const G
     }
 }
 
-void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
+void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
 {
     EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
           program, uniformCount, uniformIndices, pname, params);
@@ -7034,7 +7166,7 @@ void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const
     }
 }
 
-GLuint __stdcall glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName)
+GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName)
 {
     EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName);
 
@@ -7075,7 +7207,7 @@ GLuint __stdcall glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlo
     return 0;
 }
 
-void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params)
+void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params)
 {
     EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
           program, uniformBlockIndex, pname, params);
@@ -7134,7 +7266,7 @@ void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockInde
     }
 }
 
-void __stdcall glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName)
+void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName)
 {
     EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)",
           program, uniformBlockIndex, bufSize, length, uniformBlockName);
@@ -7176,7 +7308,7 @@ void __stdcall glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIn
     }
 }
 
-void __stdcall glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
 {
     EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)",
           program, uniformBlockIndex, uniformBlockBinding);
@@ -7225,7 +7357,7 @@ void __stdcall glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, G
     }
 }
 
-void __stdcall glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
+void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
 {
     EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
           mode, first, count, instanceCount);
@@ -7244,7 +7376,7 @@ void __stdcall glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GL
     }
 }
 
-void __stdcall glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount)
+void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount)
 {
     EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)",
           mode, count, type, indices, instanceCount);
@@ -7263,7 +7395,7 @@ void __stdcall glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
     }
 }
 
-GLsync __stdcall glFenceSync(GLenum condition, GLbitfield flags)
+GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags)
 {
     EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags);
 
@@ -7288,13 +7420,24 @@ GLsync __stdcall glFenceSync(GLenum condition, GLbitfield flags)
             return 0;
         }
 
-        return context->createFenceSync(condition);
+        GLsync fenceSync = context->createFenceSync();
+
+        gl::FenceSync *fenceSyncObject = context->getFenceSync(fenceSync);
+        gl::Error error = fenceSyncObject->set(condition);
+        if (error.isError())
+        {
+            context->deleteFenceSync(fenceSync);
+            context->recordError(error);
+            return NULL;
+        }
+
+        return fenceSync;
     }
 
     return NULL;
 }
 
-GLboolean __stdcall glIsSync(GLsync sync)
+GLboolean GL_APIENTRY glIsSync(GLsync sync)
 {
     EVENT("(GLsync sync = 0x%0.8p)", sync);
 
@@ -7313,7 +7456,7 @@ GLboolean __stdcall glIsSync(GLsync sync)
     return GL_FALSE;
 }
 
-void __stdcall glDeleteSync(GLsync sync)
+void GL_APIENTRY glDeleteSync(GLsync sync)
 {
     EVENT("(GLsync sync = 0x%0.8p)", sync);
 
@@ -7336,7 +7479,7 @@ void __stdcall glDeleteSync(GLsync sync)
     }
 }
 
-GLenum __stdcall glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+GLenum GL_APIENTRY glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
 {
     EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
           sync, flags, timeout);
@@ -7364,13 +7507,21 @@ GLenum __stdcall glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeou
             return GL_WAIT_FAILED;
         }
 
-        return fenceSync->clientWait(flags, timeout);
+        GLenum result = GL_WAIT_FAILED;
+        gl::Error error = fenceSync->clientWait(flags, timeout, &result);
+        if (error.isError())
+        {
+            context->recordError(error);
+            return GL_WAIT_FAILED;
+        }
+
+        return result;
     }
 
     return GL_FALSE;
 }
 
-void __stdcall glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+void GL_APIENTRY glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
 {
     EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
           sync, flags, timeout);
@@ -7404,11 +7555,15 @@ void __stdcall glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
             return;
         }
 
-        fenceSync->serverWait();
+        gl::Error error = fenceSync->serverWait(flags, timeout);
+        if (error.isError())
+        {
+            context->recordError(error);
+        }
     }
 }
 
-void __stdcall glGetInteger64v(GLenum pname, GLint64* params)
+void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64* params)
 {
     EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
           pname, params);
@@ -7440,7 +7595,7 @@ void __stdcall glGetInteger64v(GLenum pname, GLint64* params)
     }
 }
 
-void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values)
+void GL_APIENTRY glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values)
 {
     EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)",
           sync, pname, bufSize, length, values);
@@ -7471,10 +7626,20 @@ void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei*
         switch (pname)
         {
           case GL_OBJECT_TYPE:     values[0] = static_cast<GLint>(GL_SYNC_FENCE);              break;
-          case GL_SYNC_STATUS:     values[0] = static_cast<GLint>(fenceSync->getStatus());     break;
           case GL_SYNC_CONDITION:  values[0] = static_cast<GLint>(fenceSync->getCondition());  break;
           case GL_SYNC_FLAGS:      values[0] = 0;                                              break;
 
+          case GL_SYNC_STATUS:
+            {
+                gl::Error error = fenceSync->getStatus(values);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
+                break;
+            }
+
           default:
             context->recordError(gl::Error(GL_INVALID_ENUM));
             return;
@@ -7482,7 +7647,7 @@ void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei*
     }
 }
 
-void __stdcall glGetInteger64i_v(GLenum target, GLuint index, GLint64* data)
+void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64* data)
 {
     EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)",
           target, index, data);
@@ -7558,7 +7723,7 @@ void __stdcall glGetInteger64i_v(GLenum target, GLuint index, GLint64* data)
     }
 }
 
-void __stdcall glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params)
+void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params)
 {
     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
           target, pname, params);
@@ -7618,7 +7783,7 @@ void __stdcall glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* pa
     }
 }
 
-void __stdcall glGenSamplers(GLsizei count, GLuint* samplers)
+void GL_APIENTRY glGenSamplers(GLsizei count, GLuint* samplers)
 {
     EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers);
 
@@ -7644,7 +7809,7 @@ void __stdcall glGenSamplers(GLsizei count, GLuint* samplers)
     }
 }
 
-void __stdcall glDeleteSamplers(GLsizei count, const GLuint* samplers)
+void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint* samplers)
 {
     EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers);
 
@@ -7670,7 +7835,7 @@ void __stdcall glDeleteSamplers(GLsizei count, const GLuint* samplers)
     }
 }
 
-GLboolean __stdcall glIsSampler(GLuint sampler)
+GLboolean GL_APIENTRY glIsSampler(GLuint sampler)
 {
     EVENT("(GLuint sampler = %u)", sampler);
 
@@ -7689,7 +7854,7 @@ GLboolean __stdcall glIsSampler(GLuint sampler)
     return GL_FALSE;
 }
 
-void __stdcall glBindSampler(GLuint unit, GLuint sampler)
+void GL_APIENTRY glBindSampler(GLuint unit, GLuint sampler)
 {
     EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler);
 
@@ -7718,7 +7883,7 @@ void __stdcall glBindSampler(GLuint unit, GLuint sampler)
     }
 }
 
-void __stdcall glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)
+void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)
 {
     EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param);
 
@@ -7751,12 +7916,12 @@ void __stdcall glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)
     }
 }
 
-void __stdcall glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param)
+void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param)
 {
     glSamplerParameteri(sampler, pname, *param);
 }
 
-void __stdcall glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
+void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
 {
     EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param);
 
@@ -7789,12 +7954,12 @@ void __stdcall glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
     }
 }
 
-void __stdcall glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param)
+void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param)
 {
     glSamplerParameterf(sampler, pname, *param);
 }
 
-void __stdcall glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params)
+void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params)
 {
     EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params);
 
@@ -7822,7 +7987,7 @@ void __stdcall glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* para
     }
 }
 
-void __stdcall glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params)
+void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params)
 {
     EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params);
 
@@ -7850,7 +8015,7 @@ void __stdcall glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* pa
     }
 }
 
-void __stdcall glVertexAttribDivisor(GLuint index, GLuint divisor)
+void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor)
 {
     EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor);
 
@@ -7873,7 +8038,7 @@ void __stdcall glVertexAttribDivisor(GLuint index, GLuint divisor)
     }
 }
 
-void __stdcall glBindTransformFeedback(GLenum target, GLuint id)
+void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id)
 {
     EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
 
@@ -7916,7 +8081,7 @@ void __stdcall glBindTransformFeedback(GLenum target, GLuint id)
     }
 }
 
-void __stdcall glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
+void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
 {
     EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids);
 
@@ -7936,7 +8101,7 @@ void __stdcall glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
     }
 }
 
-void __stdcall glGenTransformFeedbacks(GLsizei n, GLuint* ids)
+void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint* ids)
 {
     EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
 
@@ -7956,7 +8121,7 @@ void __stdcall glGenTransformFeedbacks(GLsizei n, GLuint* ids)
     }
 }
 
-GLboolean __stdcall glIsTransformFeedback(GLuint id)
+GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id)
 {
     EVENT("(GLuint id = %u)", id);
 
@@ -7975,7 +8140,7 @@ GLboolean __stdcall glIsTransformFeedback(GLuint id)
     return GL_FALSE;
 }
 
-void __stdcall glPauseTransformFeedback(void)
+void GL_APIENTRY glPauseTransformFeedback(void)
 {
     EVENT("(void)");
 
@@ -8002,7 +8167,7 @@ void __stdcall glPauseTransformFeedback(void)
     }
 }
 
-void __stdcall glResumeTransformFeedback(void)
+void GL_APIENTRY glResumeTransformFeedback(void)
 {
     EVENT("(void)");
 
@@ -8029,7 +8194,7 @@ void __stdcall glResumeTransformFeedback(void)
     }
 }
 
-void __stdcall glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)
+void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)
 {
     EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)",
           program, bufSize, length, binaryFormat, binary);
@@ -8048,7 +8213,7 @@ void __stdcall glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* leng
     }
 }
 
-void __stdcall glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length)
+void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length)
 {
     EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
           program, binaryFormat, binary, length);
@@ -8067,7 +8232,7 @@ void __stdcall glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid
     }
 }
 
-void __stdcall glProgramParameteri(GLuint program, GLenum pname, GLint value)
+void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value)
 {
     EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)",
           program, pname, value);
@@ -8086,7 +8251,7 @@ void __stdcall glProgramParameteri(GLuint program, GLenum pname, GLint value)
     }
 }
 
-void __stdcall glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments)
+void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments)
 {
     EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)",
           target, numAttachments, attachments);
@@ -8106,14 +8271,21 @@ void __stdcall glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, co
         }
 
         gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
-        if (framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
+        ASSERT(framebuffer);
+
+        if (framebuffer->completeness(context->getData()) == GL_FRAMEBUFFER_COMPLETE)
         {
-            framebuffer->invalidate(context->getCaps(), numAttachments, attachments);
+            gl::Error error = framebuffer->invalidate(context->getCaps(), numAttachments, attachments);
+            if (error.isError())
+            {
+                context->recordError(error);
+                return;
+            }
         }
     }
 }
 
-void __stdcall glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height)
+void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height)
 {
     EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, "
           "GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
@@ -8134,14 +8306,21 @@ void __stdcall glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
         }
 
         gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
-        if (framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
+        ASSERT(framebuffer);
+
+        if (framebuffer->completeness(context->getData()) == GL_FRAMEBUFFER_COMPLETE)
         {
-            framebuffer->invalidateSub(context->getCaps(), numAttachments, attachments, x, y, width, height);
+            gl::Error error = framebuffer->invalidateSub(numAttachments, attachments, x, y, width, height);
+            if (error.isError())
+            {
+                context->recordError(error);
+                return;
+            }
         }
     }
 }
 
-void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
 {
     EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
           target, levels, internalformat, width, height);
@@ -8165,14 +8344,24 @@ void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalform
           case GL_TEXTURE_2D:
             {
                 gl::Texture2D *texture2d = context->getTexture2D();
-                texture2d->storage(levels, internalformat, width, height);
+                gl::Error error = texture2d->storage(levels, internalformat, width, height);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
           case GL_TEXTURE_CUBE_MAP:
             {
                 gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
-                textureCube->storage(levels, internalformat, width);
+                gl::Error error = textureCube->storage(levels, internalformat, width);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -8183,7 +8372,7 @@ void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalform
     }
 }
 
-void __stdcall glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
 {
     EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
           "GLsizei height = %d, GLsizei depth = %d)",
@@ -8208,14 +8397,24 @@ void __stdcall glTexStorage3D(GLenum target, GLsizei levels, GLenum internalform
           case GL_TEXTURE_3D:
             {
                 gl::Texture3D *texture3d = context->getTexture3D();
-                texture3d->storage(levels, internalformat, width, height, depth);
+                gl::Error error = texture3d->storage(levels, internalformat, width, height, depth);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
           case GL_TEXTURE_2D_ARRAY:
             {
                 gl::Texture2DArray *texture2darray = context->getTexture2DArray();
-                texture2darray->storage(levels, internalformat, width, height, depth);
+                gl::Error error = texture2darray->storage(levels, internalformat, width, height, depth);
+                if (error.isError())
+                {
+                    context->recordError(error);
+                    return;
+                }
             }
             break;
 
@@ -8225,7 +8424,7 @@ void __stdcall glTexStorage3D(GLenum target, GLsizei levels, GLenum internalform
     }
 }
 
-void __stdcall glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
+void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
 {
     EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, "
           "GLint* params = 0x%0.8p)",
@@ -8281,7 +8480,7 @@ void __stdcall glGetInternalformativ(GLenum target, GLenum internalformat, GLenu
 
 // Extension functions
 
-void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                                       GLbitfield mask, GLenum filter)
 {
     EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
@@ -8299,12 +8498,17 @@ void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi
             return;
         }
 
-        context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
-                                 mask, filter);
+        gl::Error error = context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
+                                                   mask, filter);
+        if (error.isError())
+        {
+            context->recordError(error);
+            return;
+        }
     }
 }
 
-void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
+void GL_APIENTRY glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
                                GLint border, GLenum format, GLenum type, const GLvoid* pixels)
 {
     EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
@@ -8315,7 +8519,7 @@ void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat
     UNIMPLEMENTED();   // FIXME
 }
 
-void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length,
+void GL_APIENTRY glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length,
                                      GLenum *binaryFormat, void *binary)
 {
     EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)",
@@ -8340,15 +8544,16 @@ void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l
             return;
         }
 
-        if (!programBinary->save(binaryFormat, binary, bufSize, length))
+        gl::Error error = programBinary->save(binaryFormat, binary, bufSize, length);
+        if (error.isError())
         {
-            context->recordError(gl::Error(GL_INVALID_OPERATION));
+            context->recordError(error);
             return;
         }
     }
 }
 
-void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat,
+void GL_APIENTRY glProgramBinaryOES(GLuint program, GLenum binaryFormat,
                                   const void *binary, GLint length)
 {
     EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)",
@@ -8371,11 +8576,16 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat,
             return;
         }
 
-        context->setProgramBinary(program, binaryFormat, binary, length);
+        gl::Error error = context->setProgramBinary(program, binaryFormat, binary, length);
+        if (error.isError())
+        {
+            context->recordError(error);
+            return;
+        }
     }
 }
 
-void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
+void GL_APIENTRY glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
 {
     EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs);
 
@@ -8388,6 +8598,8 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
             return;
         }
 
+        ASSERT(context->getState().getDrawFramebuffer());
+
         if (context->getState().getDrawFramebuffer()->id() == 0)
         {
             if (n != 1)
@@ -8416,6 +8628,7 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
         }
 
         gl::Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
+        ASSERT(framebuffer);
 
         for (unsigned int colorAttachment = 0; colorAttachment < static_cast<unsigned int>(n); colorAttachment++)
         {
@@ -8429,7 +8642,7 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
     }
 }
 
-void __stdcall glGetBufferPointervOES(GLenum target, GLenum pname, void** params)
+void GL_APIENTRY glGetBufferPointervOES(GLenum target, GLenum pname, void** params)
 {
     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
 
@@ -8461,7 +8674,7 @@ void __stdcall glGetBufferPointervOES(GLenum target, GLenum pname, void** params
     }
 }
 
-void * __stdcall glMapBufferOES(GLenum target, GLenum access)
+void * GL_APIENTRY glMapBufferOES(GLenum target, GLenum access)
 {
     EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access);
 
@@ -8507,7 +8720,7 @@ void * __stdcall glMapBufferOES(GLenum target, GLenum access)
     return NULL;
 }
 
-GLboolean __stdcall glUnmapBufferOES(GLenum target)
+GLboolean GL_APIENTRY glUnmapBufferOES(GLenum target)
 {
     EVENT("(GLenum target = 0x%X)", target);
 
@@ -8543,7 +8756,7 @@ GLboolean __stdcall glUnmapBufferOES(GLenum target)
     return GL_FALSE;
 }
 
-void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
 {
     EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
           target, offset, length, access);
@@ -8638,7 +8851,7 @@ void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr
     return NULL;
 }
 
-void __stdcall glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length)
+void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length)
 {
     EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
 
@@ -8686,7 +8899,7 @@ void __stdcall glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsi
     }
 }
 
-__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname)
+__eglMustCastToProperFunctionPointerType EGLAPIENTRY glGetProcAddress(const char *procname)
 {
     struct Extension
     {
@@ -8744,7 +8957,7 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *
 
 // Non-public functions used by EGL
 
-bool __stdcall glBindTexImage(egl::Surface *surface)
+bool EGLAPIENTRY glBindTexImage(egl::Surface *surface)
 {
     EVENT("(egl::Surface* surface = 0x%0.8p)",
           surface);
diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp
index 51447e273af..00f63ae079c 100644
--- a/src/3rdparty/angle/src/libGLESv2/main.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/main.cpp
@@ -11,24 +11,42 @@
 
 #include "common/tls.h"
 
-#if defined(ANGLE_PLATFORM_WINRT)
-__declspec(thread)
-#endif
-static TLSIndex currentTLS = TLS_OUT_OF_INDEXES;
+static TLSIndex currentTLS = TLS_INVALID_INDEX;
 
 namespace gl
 {
 
-Current *AllocateCurrent()
+// TODO(kbr): figure out how these are going to be managed on
+// non-Windows platforms. These routines would need to be exported
+// from ANGLE and called cooperatively when users create and destroy
+// threads -- or the initialization of the TLS index, and allocation
+// of thread-local data, will have to be done lazily. Will have to use
+// destructor function with pthread_create_key on POSIX platforms to
+// clean up thread-local data.
+
+// Call this exactly once at process startup.
+bool CreateThreadLocalIndex()
 {
-#if defined(ANGLE_PLATFORM_WINRT)
-    if (currentTLS == TLS_OUT_OF_INDEXES)
+    currentTLS = CreateTLSIndex();
+    if (currentTLS == TLS_INVALID_INDEX)
     {
-        currentTLS = CreateTLSIndex();
+        return false;
     }
-#endif
-    ASSERT(currentTLS != TLS_OUT_OF_INDEXES);
-    if (currentTLS == TLS_OUT_OF_INDEXES)
+    return true;
+}
+
+// Call this exactly once at process shutdown.
+void DestroyThreadLocalIndex()
+{
+    DestroyTLSIndex(currentTLS);
+    currentTLS = TLS_INVALID_INDEX;
+}
+
+// Call this upon thread startup.
+Current *AllocateCurrent()
+{
+    ASSERT(currentTLS != TLS_INVALID_INDEX);
+    if (currentTLS == TLS_INVALID_INDEX)
     {
         return NULL;
     }
@@ -46,14 +64,9 @@ Current *AllocateCurrent()
     return current;
 }
 
+// Call this upon thread shutdown.
 void DeallocateCurrent()
 {
-#if defined(ANGLE_PLATFORM_WINRT)
-    if (currentTLS == TLS_OUT_OF_INDEXES)
-    {
-        return;
-    }
-#endif
     Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
     SafeDelete(current);
     SetTLSValue(currentTLS, NULL);
@@ -61,22 +74,21 @@ void DeallocateCurrent()
 
 }
 
-#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
-
+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC)
 extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
 {
     switch (reason)
     {
       case DLL_PROCESS_ATTACH:
         {
-#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain
-            return DisableThreadLibraryCalls(instance);
-#endif
-            currentTLS = CreateTLSIndex();
-            if (currentTLS == TLS_OUT_OF_INDEXES)
+            if (!gl::CreateThreadLocalIndex())
             {
                 return FALSE;
             }
+
+#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
+            gl::InitializeDebugAnnotations();
+#endif
         }
         // Fall through to initialize index
       case DLL_THREAD_ATTACH:
@@ -91,9 +103,11 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
         break;
       case DLL_PROCESS_DETACH:
         {
-#if !defined(ANGLE_PLATFORM_WINRT)
             gl::DeallocateCurrent();
-            DestroyTLSIndex(currentTLS);
+            gl::DestroyThreadLocalIndex();
+
+#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
+            gl::UninitializeDebugAnnotations();
 #endif
         }
         break;
@@ -103,8 +117,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
 
     return TRUE;
 }
-
-#endif // !QT_OPENGL_ES_2_ANGLE_STATIC
+#endif // ANGLE_PLATFORM_WINDOWS && !QT_OPENGL_ES_2_ANGLE_STATIC
 
 namespace gl
 {
@@ -152,7 +165,7 @@ Context *getNonLostContext()
     {
         if (context->isContextLost())
         {
-            gl::error(GL_OUT_OF_MEMORY);
+            context->recordError(Error(GL_OUT_OF_MEMORY, "Context has been lost."));
             return NULL;
         }
         else
@@ -170,32 +183,4 @@ egl::Display *getDisplay()
     return current->display;
 }
 
-// Records an error code
-void error(GLenum errorCode)
-{
-    gl::Context *context = glGetCurrentContext();
-    context->recordError(Error(errorCode));
-
-    switch (errorCode)
-    {
-      case GL_INVALID_ENUM:
-        TRACE("\t! Error generated: invalid enum\n");
-        break;
-      case GL_INVALID_VALUE:
-        TRACE("\t! Error generated: invalid value\n");
-        break;
-      case GL_INVALID_OPERATION:
-        TRACE("\t! Error generated: invalid operation\n");
-        break;
-      case GL_OUT_OF_MEMORY:
-        TRACE("\t! Error generated: out of memory\n");
-        break;
-      case GL_INVALID_FRAMEBUFFER_OPERATION:
-        TRACE("\t! Error generated: invalid framebuffer operation\n");
-        break;
-      default: UNREACHABLE();
-    }
-}
-
 }
-
diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h
index c30ad3375c9..dff02787f56 100644
--- a/src/3rdparty/angle/src/libGLESv2/main.h
+++ b/src/3rdparty/angle/src/libGLESv2/main.h
@@ -14,14 +14,11 @@
 #include <GLES2/gl2.h>
 #include <EGL/egl.h>
 
-#ifndef Sleep
-#define Sleep(ms) WaitForSingleObjectEx(GetCurrentThread(), ms, FALSE)
-#endif
-
 namespace egl
 {
 class Display;
 class Surface;
+class AttributeMap;
 }
 
 namespace gl
@@ -40,16 +37,6 @@ Context *getContext();
 Context *getNonLostContext();
 egl::Display *getDisplay();
 
-void error(GLenum errorCode);
-
-template<class T>
-const T &error(GLenum errorCode, const T &returnValue)
-{
-    error(errorCode);
-
-    return returnValue;
-}
-
 }
 
 namespace rx
@@ -64,11 +51,11 @@ gl::Context *glCreateContext(int clientVersion, const gl::Context *shareContext,
 void glDestroyContext(gl::Context *context);
 void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
 gl::Context *glGetCurrentContext();
-rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType);
+rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attribMap);
 void glDestroyRenderer(rx::Renderer *renderer);
 
-__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
-bool __stdcall glBindTexImage(egl::Surface *surface);
+__eglMustCastToProperFunctionPointerType EGLAPIENTRY glGetProcAddress(const char *procname);
+bool EGLAPIENTRY glBindTexImage(egl::Surface *surface);
 }
 
 #endif   // LIBGLESV2_MAIN_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h
index f0b5f022276..c031effabd6 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h
@@ -12,6 +12,8 @@
 #include "common/angleutils.h"
 #include "libGLESv2/Buffer.h"
 
+#include <cstdint>
+
 namespace rx
 {
 
@@ -21,7 +23,6 @@ class BufferImpl
     virtual ~BufferImpl() { }
 
     virtual gl::Error setData(const void* data, size_t size, GLenum usage) = 0;
-    virtual void *getData() = 0;
     virtual gl::Error setSubData(const void* data, size_t size, size_t offset) = 0;
     virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) = 0;
     virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h
index d54e6becd3e..1dd46785d99 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h
@@ -4,29 +4,47 @@
 // found in the LICENSE file.
 //
 
-// FenceImpl.h: Defines the rx::FenceImpl class.
+// FenceImpl.h: Defines the rx::FenceNVImpl and rx::FenceSyncImpl classes.
 
 #ifndef LIBGLESV2_RENDERER_FENCEIMPL_H_
 #define LIBGLESV2_RENDERER_FENCEIMPL_H_
 
+#include "libGLESv2/Error.h"
+
 #include "common/angleutils.h"
 
+#include "angle_gl.h"
+
 namespace rx
 {
 
-class FenceImpl
+class FenceNVImpl
+{
+  public:
+    FenceNVImpl() { };
+    virtual ~FenceNVImpl() { };
+
+    virtual gl::Error set() = 0;
+    virtual gl::Error test(bool flushCommandBuffer, GLboolean *outFinished) = 0;
+    virtual gl::Error finishFence(GLboolean *outFinished) = 0;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(FenceNVImpl);
+};
+
+class FenceSyncImpl
 {
   public:
-    FenceImpl() { };
-    virtual ~FenceImpl() { };
+    FenceSyncImpl() { };
+    virtual ~FenceSyncImpl() { };
 
-    virtual bool isSet() const = 0;
-    virtual void set() = 0;
-    virtual bool test(bool flushCommandBuffer) = 0;
-    virtual bool hasError() const = 0;
+    virtual gl::Error set() = 0;
+    virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0;
+    virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0;
+    virtual gl::Error getStatus(GLint *outResult) = 0;
 
   private:
-    DISALLOW_COPY_AND_ASSIGN(FenceImpl);
+    DISALLOW_COPY_AND_ASSIGN(FenceSyncImpl);
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp
index 370b086233e..5b9b75f5626 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp
@@ -4,18 +4,20 @@
 // found in the LICENSE file.
 //
 
-// Image.h: Implements the rx::Image class, an abstract base class for the 
+// Image.h: Implements the rx::Image class, an abstract base class for the
 // renderer-specific classes which will define the interface to the underlying
 // surfaces or resources.
 
 #include "libGLESv2/renderer/Image.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/main.h"
 
 namespace rx
 {
 
 Image::Image()
 {
-    mWidth = 0; 
+    mWidth = 0;
     mHeight = 0;
     mDepth = 0;
     mInternalFormat = GL_NONE;
@@ -25,4 +27,20 @@ Image::Image()
     mDirty = false;
 }
 
+gl::Error Image::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &area, gl::Framebuffer *source)
+{
+    gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer();
+    ASSERT(colorbuffer);
+
+    RenderTarget *renderTarget = NULL;
+    gl::Error error = GetAttachmentRenderTarget(colorbuffer, &renderTarget);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ASSERT(renderTarget);
+    return copy(xoffset, yoffset, zoffset, area, renderTarget);
+}
+
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h
index 3bfc6637621..9071a88c671 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h
@@ -4,7 +4,7 @@
 // found in the LICENSE file.
 //
 
-// Image.h: Defines the rx::Image class, an abstract base class for the 
+// Image.h: Defines the rx::Image class, an abstract base class for the
 // renderer-specific classes which will define the interface to the underlying
 // surfaces or resources.
 
@@ -12,18 +12,22 @@
 #define LIBGLESV2_RENDERER_IMAGE_H_
 
 #include "common/debug.h"
+#include "libGLESv2/Error.h"
 
 #include <GLES2/gl2.h>
 
 namespace gl
 {
 class Framebuffer;
+struct Rectangle;
+struct ImageIndex;
 }
 
 namespace rx
 {
-
-class Renderer;
+class RendererD3D;
+class RenderTarget;
+class TextureStorage;
 
 class Image
 {
@@ -43,14 +47,17 @@ class Image
     void markClean() {mDirty = false;}
     virtual bool isDirty() const = 0;
 
-    virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) = 0;
+    virtual bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) = 0;
 
-    virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                          GLint unpackAlignment, GLenum type, const void *input) = 0;
-    virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                                    const void *input) = 0;
+    virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                               GLint unpackAlignment, GLenum type, const void *input) = 0;
+    virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                                         const void *input) = 0;
 
-    virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
+    gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, gl::Framebuffer *source);
+    virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source) = 0;
+    virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea,
+                           const gl::ImageIndex &sourceIndex, TextureStorage *source) = 0;
 
   protected:
     GLsizei mWidth;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp
index f68ac383de8..d472e1499e3 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp
@@ -111,11 +111,7 @@ IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c)
 
 bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const
 {
-#if defined(_MSC_VER) && _MSC_VER < 1600
-    return std::tr1::make_tuple(type, offset, count) < std::tr1::make_tuple(rhs.type, rhs.offset, rhs.count);
-#else
     return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count);
-#endif
 }
 
 IndexRangeCache::IndexBounds::IndexBounds()
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp
new file mode 100644
index 00000000000..f9fcad38a46
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp
@@ -0,0 +1,146 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
+
+#include "libGLESv2/renderer/ProgramImpl.h"
+
+#include "common/utilities.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+namespace
+{
+
+unsigned int ParseAndStripArrayIndex(std::string* name)
+{
+    unsigned int subscript = GL_INVALID_INDEX;
+
+    // Strip any trailing array operator and retrieve the subscript
+    size_t open = name->find_last_of('[');
+    size_t close = name->find_last_of(']');
+    if (open != std::string::npos && close == name->length() - 1)
+    {
+        subscript = atoi(name->substr(open + 1).c_str());
+        name->erase(open);
+    }
+
+    return subscript;
+}
+
+}
+
+ProgramImpl::~ProgramImpl()
+{
+    // Ensure that reset was called by the inherited class during destruction
+    ASSERT(mUniformIndex.size() == 0);
+}
+
+gl::LinkedUniform *ProgramImpl::getUniformByLocation(GLint location) const
+{
+    ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformIndex.size());
+    return mUniforms[mUniformIndex[location].index];
+}
+
+gl::LinkedUniform *ProgramImpl::getUniformByName(const std::string &name) const
+{
+    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+    {
+        if (mUniforms[uniformIndex]->name == name)
+        {
+            return mUniforms[uniformIndex];
+        }
+    }
+
+    return NULL;
+}
+
+gl::UniformBlock *ProgramImpl::getUniformBlockByIndex(GLuint blockIndex) const
+{
+    ASSERT(blockIndex < mUniformBlocks.size());
+    return mUniformBlocks[blockIndex];
+}
+
+GLint ProgramImpl::getUniformLocation(std::string name)
+{
+    unsigned int subscript = ParseAndStripArrayIndex(&name);
+
+    unsigned int numUniforms = mUniformIndex.size();
+    for (unsigned int location = 0; location < numUniforms; location++)
+    {
+        if (mUniformIndex[location].name == name)
+        {
+            const int index = mUniformIndex[location].index;
+            const bool isArray = mUniforms[index]->isArray();
+
+            if ((isArray && mUniformIndex[location].element == subscript) ||
+                (subscript == GL_INVALID_INDEX))
+            {
+                return location;
+            }
+        }
+    }
+
+    return -1;
+}
+
+GLuint ProgramImpl::getUniformIndex(std::string name)
+{
+    unsigned int subscript = ParseAndStripArrayIndex(&name);
+
+    // The app is not allowed to specify array indices other than 0 for arrays of basic types
+    if (subscript != 0 && subscript != GL_INVALID_INDEX)
+    {
+        return GL_INVALID_INDEX;
+    }
+
+    unsigned int numUniforms = mUniforms.size();
+    for (unsigned int index = 0; index < numUniforms; index++)
+    {
+        if (mUniforms[index]->name == name)
+        {
+            if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX)
+            {
+                return index;
+            }
+        }
+    }
+
+    return GL_INVALID_INDEX;
+}
+
+GLuint ProgramImpl::getUniformBlockIndex(std::string name) const
+{
+    unsigned int subscript = ParseAndStripArrayIndex(&name);
+
+    unsigned int numUniformBlocks = mUniformBlocks.size();
+    for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
+    {
+        const gl::UniformBlock &uniformBlock = *mUniformBlocks[blockIndex];
+        if (uniformBlock.name == name)
+        {
+            const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0);
+            if (subscript == uniformBlock.elementIndex || arrayElementZero)
+            {
+                return blockIndex;
+            }
+        }
+    }
+
+    return GL_INVALID_INDEX;
+}
+
+void ProgramImpl::reset()
+{
+    SafeDeleteContainer(mUniforms);
+    mUniformIndex.clear();
+    SafeDeleteContainer(mUniformBlocks);
+    mTransformFeedbackLinkedVaryings.clear();
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h
index ba0955fdf8e..6aaa23cf89d 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h
@@ -13,44 +13,113 @@
 #include "libGLESv2/BinaryStream.h"
 #include "libGLESv2/Constants.h"
 #include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/renderer/Renderer.h"
+
+#include <map>
 
 namespace rx
 {
 
-class DynamicHLSL;
-class Renderer;
-
 class ProgramImpl
 {
-public:
-    virtual ~ProgramImpl() { }
+  public:
+    ProgramImpl() { }
+    virtual ~ProgramImpl();
+
+    const std::vector<gl::LinkedUniform*> &getUniforms() const { return mUniforms; }
+    const std::vector<gl::VariableLocation> &getUniformIndices() const { return mUniformIndex; }
+    const std::vector<gl::UniformBlock*> &getUniformBlocks() const { return mUniformBlocks; }
+    const std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() const { return mTransformFeedbackLinkedVaryings; }
+    const sh::Attribute *getShaderAttributes() const { return mShaderAttributes; }
+
+    std::vector<gl::LinkedUniform*> &getUniforms() { return mUniforms; }
+    std::vector<gl::VariableLocation> &getUniformIndices() { return mUniformIndex; }
+    std::vector<gl::UniformBlock*> &getUniformBlocks() { return mUniformBlocks; }
+    std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() { return mTransformFeedbackLinkedVaryings; }
+    sh::Attribute *getShaderAttributes() { return mShaderAttributes; }
+
+    gl::LinkedUniform *getUniformByLocation(GLint location) const;
+    gl::LinkedUniform *getUniformByName(const std::string &name) const;
+    gl::UniformBlock *getUniformBlockByIndex(GLuint blockIndex) const;
 
-    // TODO: Temporary interfaces to ease migration. Remove soon!
-    virtual Renderer *getRenderer() = 0;
-    virtual DynamicHLSL *getDynamicHLSL() = 0;
-    virtual const std::vector<rx::PixelShaderOutputVariable> &getPixelShaderKey() = 0;
+    GLint getUniformLocation(std::string name);
+    GLuint getUniformIndex(std::string name);
+    GLuint getUniformBlockIndex(std::string name) const;
+
+    virtual bool usesPointSize() const = 0;
+    virtual int getShaderVersion() const = 0;
+    virtual GLenum getTransformFeedbackBufferMode() const = 0;
 
     virtual GLenum getBinaryFormat() = 0;
-    virtual bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
-    virtual bool save(gl::BinaryOutputStream *stream) = 0;
-
-    virtual rx::ShaderExecutable *getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector<GLenum> &outputSignature,
-                                                                    const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
-                                                                    bool separatedOutputBuffers) = 0;
-    virtual rx::ShaderExecutable *getVertexExecutableForInputLayout(gl::InfoLog &infoLog,
-                                                                    const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
-                                                                    const sh::Attribute shaderAttributes[],
-                                                                    const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
-                                                                    bool separatedOutputBuffers) = 0;
-
-    virtual bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
-                      const std::vector<std::string> &transformFeedbackVaryings, int *registers,
-                      std::vector<gl::LinkedVarying> *linkedVaryings, std::map<int,
-                      gl::VariableLocation> *outputVariables) = 0;
-
-    virtual void initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms) = 0;
-
-    virtual void reset() = 0;
+    virtual gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
+    virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
+
+    virtual gl::LinkResult link(const gl::Data &data, gl::InfoLog &infoLog,
+                                gl::Shader *fragmentShader, gl::Shader *vertexShader,
+                                const std::vector<std::string> &transformFeedbackVaryings,
+                                GLenum transformFeedbackBufferMode,
+                                int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
+                                std::map<int, gl::VariableLocation> *outputVariables) = 0;
+
+    virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0;
+    virtual void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) = 0;
+    virtual void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) = 0;
+    virtual void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) = 0;
+    virtual void setUniform1iv(GLint location, GLsizei count, const GLint *v) = 0;
+    virtual void setUniform2iv(GLint location, GLsizei count, const GLint *v) = 0;
+    virtual void setUniform3iv(GLint location, GLsizei count, const GLint *v) = 0;
+    virtual void setUniform4iv(GLint location, GLsizei count, const GLint *v) = 0;
+    virtual void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) = 0;
+    virtual void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) = 0;
+    virtual void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) = 0;
+    virtual void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) = 0;
+    virtual void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+    virtual void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+
+    virtual void getUniformfv(GLint location, GLfloat *params) = 0;
+    virtual void getUniformiv(GLint location, GLint *params) = 0;
+    virtual void getUniformuiv(GLint location, GLuint *params) = 0;
+
+    virtual void reset();
+
+    // TODO: The following functions are possibly only applicable to D3D backends. The should be carefully evaluated to
+    // determine if they can be removed from this interface.
+    virtual GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const = 0;
+    virtual GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const = 0;
+    virtual GLint getUsedSamplerRange(gl::SamplerType type) const = 0;
+    virtual void updateSamplerMapping() = 0;
+    virtual bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) = 0;
+
+    virtual gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
+                                                     int registers) = 0;
+
+    virtual bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader,
+                              const gl::Caps &caps) = 0;
+    virtual bool defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock,
+                                    const gl::Caps &caps) = 0;
+
+    virtual gl::Error applyUniforms() = 0;
+    virtual gl::Error applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const gl::Caps &caps) = 0;
+    virtual bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader,
+                                            unsigned int registerIndex, const gl::Caps &caps) = 0;
+
+  protected:
+    DISALLOW_COPY_AND_ASSIGN(ProgramImpl);
+
+    std::vector<gl::LinkedUniform*> mUniforms;
+    std::vector<gl::VariableLocation> mUniformIndex;
+    std::vector<gl::UniformBlock*> mUniformBlocks;
+    std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings;
+
+    sh::Attribute mShaderAttributes[gl::MAX_VERTEX_ATTRIBS];
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp
new file mode 100644
index 00000000000..857fdc9dae1
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTarget.cpp: Implements serial handling for rx::RenderTarget
+
+#include "libGLESv2/renderer/RenderTarget.h"
+
+namespace rx
+{
+unsigned int RenderTarget::mCurrentSerial = 1;
+
+RenderTarget::RenderTarget()
+    : mSerial(issueSerials(1))
+{
+}
+
+RenderTarget::~RenderTarget()
+{
+}
+
+unsigned int RenderTarget::getSerial() const
+{
+    return mSerial;
+}
+
+unsigned int RenderTarget::issueSerials(unsigned int count)
+{
+    unsigned int firstSerial = mCurrentSerial;
+    mCurrentSerial += count;
+    return firstSerial;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h
index 44637ec7de9..3bdfb0cc98e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h
@@ -18,28 +18,22 @@ namespace rx
 class RenderTarget
 {
   public:
-    RenderTarget()
-    {
-        mWidth = 0;
-        mHeight = 0;
-        mDepth = 0;
-        mInternalFormat = GL_NONE;
-        mActualFormat = GL_NONE;
-        mSamples = 0;
-    }
+    RenderTarget();
+    virtual ~RenderTarget();
 
-    virtual ~RenderTarget() {};
-
-    GLsizei getWidth() const { return mWidth; }
-    GLsizei getHeight() const { return mHeight; }
-    GLsizei getDepth() const { return mDepth; }
-    GLenum getInternalFormat() const { return mInternalFormat; }
-    GLenum getActualFormat() const { return mActualFormat; }
-    GLsizei getSamples() const { return mSamples; }
-    gl::Extents getExtents() const { return gl::Extents(mWidth, mHeight, mDepth); }
+    virtual GLsizei getWidth() const = 0;
+    virtual GLsizei getHeight() const = 0;
+    virtual GLsizei getDepth() const = 0;
+    virtual GLenum getInternalFormat() const = 0;
+    virtual GLenum getActualFormat() const = 0;
+    virtual GLsizei getSamples() const = 0;
+    gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); }
 
     virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) = 0;
 
+    virtual unsigned int getSerial() const;
+    static unsigned int issueSerials(unsigned int count);
+
     struct Desc {
         GLsizei width;
         GLsizei height;
@@ -47,16 +41,11 @@ class RenderTarget
         GLenum  format;
     };
 
-  protected:
-    GLsizei mWidth;
-    GLsizei mHeight;
-    GLsizei mDepth;
-    GLenum mInternalFormat;
-    GLenum mActualFormat;
-    GLsizei mSamples;
-
   private:
     DISALLOW_COPY_AND_ASSIGN(RenderTarget);
+
+    const unsigned int mSerial;
+    static unsigned int mCurrentSerial;
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp
new file mode 100644
index 00000000000..770ae8e9c6a
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferImpl.h: Implements the shared methods of the abstract class gl::RenderbufferImpl
+
+#include "libGLESv2/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+RenderbufferImpl::RenderbufferImpl()
+{
+}
+
+RenderbufferImpl::~RenderbufferImpl()
+{
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h
new file mode 100644
index 00000000000..52e070f1d3b
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferImpl.h: Defines the abstract class gl::RenderbufferImpl
+
+#ifndef LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_
+#define LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_
+
+#include "angle_gl.h"
+
+#include "libGLESv2/Error.h"
+
+#include "common/angleutils.h"
+
+namespace rx
+{
+
+class RenderbufferImpl
+{
+  public:
+    RenderbufferImpl();
+    virtual ~RenderbufferImpl() = 0;
+
+    virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) = 0;
+
+    virtual GLsizei getWidth() const = 0;
+    virtual GLsizei getHeight() const = 0;
+    virtual GLenum getInternalFormat() const = 0;
+    virtual GLenum getActualFormat() const = 0;
+    virtual GLsizei getSamples() const = 0;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(RenderbufferImpl);
+};
+
+}
+
+#endif   // LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
index 910d0285f18..df3dae1e383 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
@@ -6,11 +6,12 @@
 
 // Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances.
 
+#include "common/utilities.h"
+#include "libEGL/AttributeMap.h"
 #include "libGLESv2/main.h"
-#include "libGLESv2/Program.h"
 #include "libGLESv2/renderer/Renderer.h"
-#include "common/utilities.h"
-#include "libGLESv2/Shader.h"
+
+#include <EGL/eglext.h>
 
 #if defined (ANGLE_ENABLE_D3D9)
 #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
@@ -29,15 +30,12 @@
 #define ANGLE_DEFAULT_D3D11 0
 #endif
 
-#include <EGL/eglext.h>
-
 namespace rx
 {
 
-Renderer::Renderer(egl::Display *display)
-    : mDisplay(display),
-      mCapsInitialized(false),
-      mCurrentClientVersion(2)
+Renderer::Renderer()
+    : mCapsInitialized(false),
+      mWorkaroundsInitialized(false)
 {
 }
 
@@ -78,12 +76,23 @@ const gl::Extensions &Renderer::getRendererExtensions() const
     return mExtensions;
 }
 
-typedef Renderer *(*CreateRendererFunction)(egl::Display*, EGLNativeDisplayType, EGLint);
+const Workarounds &Renderer::getWorkarounds() const
+{
+    if (!mWorkaroundsInitialized)
+    {
+        mWorkarounds = generateWorkarounds();
+        mWorkaroundsInitialized = true;
+    }
+
+    return mWorkarounds;
+}
+
+typedef Renderer *(*CreateRendererFunction)(egl::Display*, EGLNativeDisplayType, const egl::AttributeMap &);
 
 template <typename RendererType>
-Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType)
+Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attributes)
 {
-    return new RendererType(display, nativeDisplay, requestedDisplayType);
+    return new RendererType(display, nativeDisplay, attributes);
 }
 
 }
@@ -91,15 +100,16 @@ Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDispl
 extern "C"
 {
 
-rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType)
+rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attribMap)
 {
     std::vector<rx::CreateRendererFunction> rendererCreationFunctions;
 
+    EGLint requestedDisplayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+
 #   if defined(ANGLE_ENABLE_D3D11)
         if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
             nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE ||
-            requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
-            requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE)
+            requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
         {
             rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer11>);
         }
@@ -138,7 +148,7 @@ rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativ
 
     for (size_t i = 0; i < rendererCreationFunctions.size(); i++)
     {
-        rx::Renderer *renderer = rendererCreationFunctions[i](display, nativeDisplay, requestedDisplayType);
+        rx::Renderer *renderer = rendererCreationFunctions[i](display, nativeDisplay, attribMap);
         if (renderer->initialize() == EGL_SUCCESS)
         {
             return renderer;
@@ -155,7 +165,8 @@ rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativ
 
 void glDestroyRenderer(rx::Renderer *renderer)
 {
-    delete renderer;
+    ASSERT(renderer);
+    SafeDelete(renderer);
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
index b2249741abf..b85895a9385 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
@@ -10,10 +10,13 @@
 #ifndef LIBGLESV2_RENDERER_RENDERER_H_
 #define LIBGLESV2_RENDERER_RENDERER_H_
 
-#include "libGLESv2/Uniform.h"
-#include "libGLESv2/angletypes.h"
 #include "libGLESv2/Caps.h"
 #include "libGLESv2/Error.h"
+#include "libGLESv2/Uniform.h"
+#include "libGLESv2/angletypes.h"
+#include "libGLESv2/renderer/Workarounds.h"
+#include "common/NativeWindow.h"
+#include "common/mathutil.h"
 
 #include <cstdint>
 
@@ -32,37 +35,26 @@ class Display;
 
 namespace gl
 {
-class InfoLog;
-class ProgramBinary;
-struct LinkedVarying;
-struct VertexAttribute;
 class Buffer;
-class Texture;
 class Framebuffer;
-struct VertexAttribCurrentValueData;
+struct Data;
 }
 
 namespace rx
 {
-class TextureStorage;
-class VertexBuffer;
-class IndexBuffer;
 class QueryImpl;
-class FenceImpl;
+class FenceNVImpl;
+class FenceSyncImpl;
 class BufferImpl;
 class VertexArrayImpl;
-class BufferStorage;
-struct TranslatedIndexData;
 class ShaderImpl;
 class ProgramImpl;
-class ShaderExecutable;
-class SwapChain;
-class RenderTarget;
-class Image;
-class TextureStorage;
-class UniformStorage;
 class TextureImpl;
 class TransformFeedbackImpl;
+class RenderbufferImpl;
+struct TranslatedIndexData;
+struct Workarounds;
+class SwapChain;
 
 struct ConfigDesc
 {
@@ -73,30 +65,10 @@ struct ConfigDesc
     bool    es3Capable;
 };
 
-struct dx_VertexConstants
-{
-    float depthRange[4];
-    float viewAdjust[4];
-};
-
-struct dx_PixelConstants
-{
-    float depthRange[4];
-    float viewCoords[4];
-    float depthFront[4];
-};
-
-enum ShaderType
-{
-    SHADER_VERTEX,
-    SHADER_PIXEL,
-    SHADER_GEOMETRY
-};
-
 class Renderer
 {
   public:
-    explicit Renderer(egl::Display *display);
+    Renderer();
     virtual ~Renderer();
 
     virtual EGLint initialize() = 0;
@@ -105,163 +77,116 @@ class Renderer
     virtual int generateConfigs(ConfigDesc **configDescList) = 0;
     virtual void deleteConfigs(ConfigDesc *configDescList) = 0;
 
-    virtual void sync(bool block) = 0;
-
-    virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
+    virtual gl::Error sync(bool block) = 0;
 
-    virtual gl::Error generateSwizzle(gl::Texture *texture) = 0;
-    virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0;
-    virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0;
+    virtual gl::Error drawArrays(const gl::Data &data, GLenum mode,
+                                 GLint first, GLsizei count, GLsizei instances) = 0;
+    virtual gl::Error drawElements(const gl::Data &data, GLenum mode, GLsizei count, GLenum type,
+                                   const GLvoid *indices, GLsizei instances,
+                                   const RangeUI &indexRange) = 0;
 
-    virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) = 0;
+    virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0;
+    virtual gl::Error clearBufferfv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLfloat *values) = 0;
+    virtual gl::Error clearBufferuiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLuint *values) = 0;
+    virtual gl::Error clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values) = 0;
+    virtual gl::Error clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0;
 
-    virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0;
-    virtual gl::Error setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
-                                    unsigned int sampleMask) = 0;
-    virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
-                                           int stencilBackRef, bool frontFaceCCW) = 0;
+    virtual gl::Error readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height,
+                                 GLenum format, GLenum type, GLsizei *bufSize, void* pixels) = 0;
 
-    virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0;
-    virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
-                             bool ignoreViewport) = 0;
-
-    virtual gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer) = 0;
-    virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
-                                   bool rasterizerDiscard, bool transformFeedbackActive) = 0;
-    virtual gl::Error applyUniforms(const gl::ProgramBinary &programBinary) = 0;
-    virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
-    virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[],
-                                        GLint first, GLsizei count, GLsizei instances) = 0;
-    virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0;
-    virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) = 0;
-
-    virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0;
-    virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
-                                   gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0;
-
-    virtual gl::Error clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) = 0;
-
-    virtual void markAllStateDirty() = 0;
-
-    // lost device
-    virtual void notifyDeviceLost() = 0;
-    virtual bool isDeviceLost() = 0;
-    virtual bool testDeviceLost(bool notify) = 0;
-    virtual bool testDeviceResettable() = 0;
-
-    // Renderer capabilities (virtual because it is used by egl::Display, do not override)
-    virtual const gl::Caps &getRendererCaps() const;
-    virtual const gl::TextureCapsMap &getRendererTextureCaps() const;
-    virtual const gl::Extensions &getRendererExtensions() const;
-
-    virtual DWORD getAdapterVendor() const = 0;
-    virtual std::string getRendererDescription() const = 0;
-    virtual GUID getAdapterIdentifier() const = 0;
+    virtual gl::Error blitFramebuffer(const gl::Data &data,
+                                      GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                                      GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                                      GLbitfield mask, GLenum filter) = 0;
 
-    virtual unsigned int getReservedVertexUniformVectors() const = 0;
-    virtual unsigned int getReservedFragmentUniformVectors() const = 0;
-    virtual unsigned int getReservedVertexUniformBuffers() const = 0;
-    virtual unsigned int getReservedFragmentUniformBuffers() const = 0;
+    // TODO(jmadill): caps? and virtual for egl::Display
     virtual bool getShareHandleSupport() const = 0;
     virtual bool getPostSubBufferSupport() const = 0;
 
-    virtual int getMajorShaderModel() const = 0;
-    virtual int getMinSwapInterval() const = 0;
-    virtual int getMaxSwapInterval() const = 0;
-
-    // Pixel operations
-    virtual bool copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source) = 0;
-    virtual bool copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source) = 0;
-    virtual bool copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source) = 0;
-    virtual bool copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source) = 0;
-
-    virtual bool copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                             GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) = 0;
-    virtual bool copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                               GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) = 0;
-    virtual bool copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                             GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0;
-    virtual bool copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                                  GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0;
-
-    virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
-                          const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) = 0;
-
-    virtual gl::Error readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
-                                 GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) = 0;
-
-    // RenderTarget creation
-    virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth) = 0;
-    virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples) = 0;
-
     // Shader creation
-    virtual ShaderImpl *createShader(GLenum type) = 0;
+    virtual ShaderImpl *createShader(const gl::Data &data, GLenum type) = 0;
     virtual ProgramImpl *createProgram() = 0;
 
     // Shader operations
     virtual void releaseShaderCompiler() = 0;
-    virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
-                                             const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
-                                             bool separatedOutputBuffers) = 0;
-    virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
-                                                  const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
-                                                  bool separatedOutputBuffers, D3DWorkaroundType workaround) = 0;
-    virtual UniformStorage *createUniformStorage(size_t storageSize) = 0;
-
-    // Image operations
-    virtual Image *createImage() = 0;
-    virtual void generateMipmap(Image *dest, Image *source) = 0;
-    virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0;
-    virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) = 0;
-    virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) = 0;
-    virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
-    virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
 
     // Texture creation
     virtual TextureImpl *createTexture(GLenum target) = 0;
 
+    // Renderbuffer creation
+    virtual RenderbufferImpl *createRenderbuffer() = 0;
+    virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth) = 0;
+
     // Buffer creation
     virtual BufferImpl *createBuffer() = 0;
-    virtual VertexBuffer *createVertexBuffer() = 0;
-    virtual IndexBuffer *createIndexBuffer() = 0;
 
     // Vertex Array creation
     virtual VertexArrayImpl *createVertexArray() = 0;
 
     // Query and Fence creation
     virtual QueryImpl *createQuery(GLenum type) = 0;
-    virtual FenceImpl *createFence() = 0;
+    virtual FenceNVImpl *createFenceNV() = 0;
+    virtual FenceSyncImpl *createFenceSync() = 0;
 
     // Transform Feedback creation
-    virtual TransformFeedbackImpl* createTransformFeedback() = 0;
+    virtual TransformFeedbackImpl *createTransformFeedback() = 0;
 
-    // Current GLES client version
-    void setCurrentClientVersion(int clientVersion) { mCurrentClientVersion = clientVersion; }
-    int getCurrentClientVersion() const { return mCurrentClientVersion; }
+    // lost device
+    //TODO(jmadill): investigate if this stuff is necessary in GL
+    virtual void notifyDeviceLost() = 0;
+    virtual bool isDeviceLost() = 0;
+    virtual bool testDeviceLost(bool notify) = 0;
+    virtual bool testDeviceResettable() = 0;
 
-    // Buffer-to-texture and Texture-to-buffer copies
-    virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0;
-    virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
-                                         GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0;
+    virtual DWORD getAdapterVendor() const = 0;
+    virtual std::string getRendererDescription() const = 0;
+    virtual GUID getAdapterIdentifier() const = 0;
 
-    virtual bool getLUID(LUID *adapterLuid) const = 0;
-    virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0;
-    virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0;
+    // Renderer capabilities (virtual because of egl::Display)
+    virtual const gl::Caps &getRendererCaps() const;
+    const gl::TextureCapsMap &getRendererTextureCaps() const;
+    virtual const gl::Extensions &getRendererExtensions() const;
+    const Workarounds &getWorkarounds() const;
 
-  protected:
-    egl::Display *mDisplay;
+    // TODO(jmadill): needed by egl::Display, probably should be removed
+    virtual int getMajorShaderModel() const = 0;
+    virtual int getMinSwapInterval() const = 0;
+    virtual int getMaxSwapInterval() const = 0;
+    virtual bool getLUID(LUID *adapterLuid) const = 0;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Renderer);
 
     virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0;
+    virtual Workarounds generateWorkarounds() const = 0;
 
     mutable bool mCapsInitialized;
     mutable gl::Caps mCaps;
     mutable gl::TextureCapsMap mTextureCaps;
     mutable gl::Extensions mExtensions;
 
-    int mCurrentClientVersion;
+    mutable bool mWorkaroundsInitialized;
+    mutable Workarounds mWorkarounds;
+};
+
+struct dx_VertexConstants
+{
+    float depthRange[4];
+    float viewAdjust[4];
+};
+
+struct dx_PixelConstants
+{
+    float depthRange[4];
+    float viewCoords[4];
+    float depthFront[4];
+};
+
+enum ShaderType
+{
+    SHADER_VERTEX,
+    SHADER_PIXEL,
+    SHADER_GEOMETRY
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h
index f17195673da..f1a96d74fb2 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h
@@ -40,10 +40,21 @@ class ShaderExecutable
         return mFunctionBuffer.size();
     }
 
+    const std::string &getDebugInfo() const
+    {
+        return mDebugInfo;
+    }
+
+    void appendDebugInfo(const std::string &info)
+    {
+        mDebugInfo += info;
+    }
+
   private:
     DISALLOW_COPY_AND_ASSIGN(ShaderExecutable);
 
     std::vector<uint8_t> mFunctionBuffer;
+    std::string mDebugInfo;
 };
 
 class UniformStorage
@@ -64,4 +75,4 @@ class UniformStorage
 
 }
 
-#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_
+#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h
index de5d30e6feb..cb0d360f0b2 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h
@@ -23,9 +23,10 @@ class ShaderImpl
     ShaderImpl() { }
     virtual ~ShaderImpl() { }
 
-    virtual bool compile(const std::string &source) = 0;
+    virtual bool compile(const gl::Data &data, const std::string &source) = 0;
     virtual const std::string &getInfoLog() const = 0;
     virtual const std::string &getTranslatedSource() const = 0;
+    virtual std::string getDebugInfo() const = 0;
 
     const std::vector<gl::PackedVarying> &getVaryings() const { return mVaryings; }
     const std::vector<sh::Uniform> &getUniforms() const { return mUniforms; }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
index 1ec702f2999..1417e0bdf6a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
@@ -11,28 +11,24 @@
 #define LIBGLESV2_RENDERER_SWAPCHAIN_H_
 
 #include "common/angleutils.h"
+#include "common/NativeWindow.h"
 #include "common/platform.h"
 
 #include <GLES2/gl2.h>
 #include <EGL/egl.h>
-#include <EGL/eglplatform.h>
+
+#if !defined(ANGLE_FORCE_VSYNC_OFF)
+#define ANGLE_FORCE_VSYNC_OFF 0
+#endif
 
 namespace rx
 {
 
-enum SwapFlags
-{
-    SWAP_NORMAL = 0,
-    SWAP_ROTATE_90 = 1,
-    SWAP_ROTATE_270 = 2,
-    SWAP_ROTATE_180 = SWAP_ROTATE_90|SWAP_ROTATE_270,
-};
-
 class SwapChain
 {
   public:
-    SwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
-        : mWindow(window), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat)
+    SwapChain(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+        : mNativeWindow(nativeWindow), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat)
     {
     }
 
@@ -40,13 +36,16 @@ class SwapChain
 
     virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0;
     virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0;
-    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags) = 0;
+    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
     virtual void recreate() = 0;
 
+    GLenum GetBackBufferInternalFormat() const { return mBackBufferFormat; }
+    GLenum GetDepthBufferInternalFormat() const { return mDepthBufferFormat; }
+
     virtual HANDLE getShareHandle() {return mShareHandle;};
 
   protected:
-    const EGLNativeWindowType mWindow;            // Window that the surface is created for.
+    rx::NativeWindow mNativeWindow;  // Handler for the Window that the surface is created for.
     const GLenum mBackBufferFormat;
     const GLenum mDepthBufferFormat;
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h
index e3cc50d6809..3e662557e4f 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h
@@ -10,6 +10,7 @@
 #define LIBGLESV2_RENDERER_TEXTUREIMPL_H_
 
 #include "common/angleutils.h"
+#include "libGLESv2/Error.h"
 
 #include "angle_gl.h"
 
@@ -31,19 +32,12 @@ namespace rx
 {
 
 class Image;
-class Renderer;
-class TextureStorage;
 
 class TextureImpl
 {
   public:
     virtual ~TextureImpl() {};
 
-    // TODO: If this methods could go away that would be ideal;
-    // TextureStorage should only be necessary for the D3D backend, and as such
-    // higher level code should not rely on it.
-    virtual TextureStorage *getNativeTexture() = 0;
-
     // Deprecated in favour of the ImageIndex method
     virtual Image *getImage(int level, int layer) const = 0;
     virtual Image *getImage(const gl::ImageIndex &index) const = 0;
@@ -51,15 +45,15 @@ class TextureImpl
 
     virtual void setUsage(GLenum usage) = 0;
 
-    virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
-    virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) = 0;
-    virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
-    virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) = 0;
-    virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
-    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
-    virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0;
+    virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
+    virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
+    virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
+    virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
+    virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
+    virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
+    virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0;
 
-    virtual void generateMipmaps() = 0;
+    virtual gl::Error generateMipmaps() = 0;
 
     virtual void bindTexImage(egl::Surface *surface) = 0;
     virtual void releaseTexImage() = 0;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h b/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h
new file mode 100644
index 00000000000..20a166fb7a0
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angletypes.h: Workarounds for driver bugs and other issues.
+
+#ifndef LIBGLESV2_RENDERER_WORKAROUNDS_H_
+#define LIBGLESV2_RENDERER_WORKAROUNDS_H_
+
+// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate
+// independent of ANGLE's renderer. Workarounds should also be accessible
+// outside of the Renderer.
+
+namespace rx
+{
+
+enum D3DWorkaroundType
+{
+    ANGLE_D3D_WORKAROUND_NONE,
+    ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION,
+    ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION
+};
+
+struct Workarounds
+{
+    Workarounds()
+        : mrtPerfWorkaround(false),
+          setDataFasterThanImageUpload(false)
+    {}
+
+    bool mrtPerfWorkaround;
+    bool setDataFasterThanImageUpload;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_WORKAROUNDS_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp
index 004223d70f8..aabc9f04e9b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp
@@ -6,7 +6,7 @@
 
 // copyimage.cpp: Defines image copying functions
 
-#include "libGLESv2/renderer/copyImage.h"
+#include "libGLESv2/renderer/copyimage.h"
 
 namespace rx
 {
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp
index a34ef03fb85..dd0d3f52ad4 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp
@@ -9,7 +9,6 @@
 #include "libGLESv2/renderer/d3d/BufferD3D.h"
 #include "libGLESv2/renderer/d3d/VertexBuffer.h"
 #include "libGLESv2/renderer/d3d/IndexBuffer.h"
-#include "libGLESv2/renderer/Renderer.h"
 #include "libGLESv2/main.h"
 
 namespace rx
@@ -37,6 +36,13 @@ BufferD3D *BufferD3D::makeBufferD3D(BufferImpl *buffer)
     return static_cast<BufferD3D*>(buffer);
 }
 
+BufferD3D *BufferD3D::makeFromBuffer(gl::Buffer *buffer)
+{
+    BufferImpl *impl = buffer->getImplementation();
+    ASSERT(impl);
+    return makeBufferD3D(impl);
+}
+
 void BufferD3D::updateSerial()
 {
     mSerial = mNextSerial++;
@@ -46,11 +52,11 @@ void BufferD3D::initializeStaticData()
 {
     if (!mStaticVertexBuffer)
     {
-        mStaticVertexBuffer = new rx::StaticVertexBufferInterface(getRenderer());
+        mStaticVertexBuffer = new StaticVertexBufferInterface(getRenderer());
     }
     if (!mStaticIndexBuffer)
     {
-        mStaticIndexBuffer = new rx::StaticIndexBufferInterface(getRenderer());
+        mStaticIndexBuffer = new StaticIndexBufferInterface(getRenderer());
     }
 }
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h
index 44f14cee589..1a1308c545a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h
@@ -12,10 +12,11 @@
 #include "libGLESv2/renderer/BufferImpl.h"
 #include "libGLESv2/angletypes.h"
 
+#include <cstdint>
+
 namespace rx
 {
-
-class Renderer;
+class RendererD3D;
 class StaticIndexBufferInterface;
 class StaticVertexBufferInterface;
 
@@ -26,15 +27,17 @@ class BufferD3D : public BufferImpl
     virtual ~BufferD3D();
 
     static BufferD3D *makeBufferD3D(BufferImpl *buffer);
+    static BufferD3D *makeFromBuffer(gl::Buffer *buffer);
 
     unsigned int getSerial() const { return mSerial; }
 
+    virtual gl::Error getData(const uint8_t **outData) = 0;
     virtual size_t getSize() const = 0;
     virtual bool supportsDirectBinding() const = 0;
-    virtual Renderer* getRenderer() = 0;
+    virtual RendererD3D *getRenderer() = 0;
 
-    rx::StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; }
-    rx::StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; }
+    StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; }
+    StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; }
 
     void initializeStaticData();
     void invalidateStaticData();
@@ -46,8 +49,8 @@ class BufferD3D : public BufferImpl
 
     void updateSerial();
 
-    rx::StaticVertexBufferInterface *mStaticVertexBuffer;
-    rx::StaticIndexBufferInterface *mStaticIndexBuffer;
+    StaticVertexBufferInterface *mStaticVertexBuffer;
+    StaticIndexBufferInterface *mStaticIndexBuffer;
     unsigned int mUnmodifiedDataUse;
 };
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp
index 13411ebe64a..3d5bfe0cbea 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp
@@ -8,10 +8,10 @@
 
 #include "libGLESv2/renderer/d3d/DynamicHLSL.h"
 #include "libGLESv2/renderer/d3d/ShaderD3D.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/Shader.h"
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
 #include "libGLESv2/Program.h"
 #include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/Shader.h"
 #include "libGLESv2/formatutils.h"
 
 #include "common/utilities.h"
@@ -22,6 +22,9 @@ META_ASSERT(GL_INVALID_INDEX == UINT_MAX);
 
 using namespace gl;
 
+namespace rx
+{
+
 namespace
 {
 
@@ -70,7 +73,7 @@ std::string HLSLTypeString(GLenum type)
     return HLSLComponentTypeString(gl::VariableComponentType(type), gl::VariableComponentCount(type));
 }
 
-const rx::PixelShaderOutputVariable &GetOutputAtLocation(const std::vector<rx::PixelShaderOutputVariable> &outputVariables,
+const PixelShaderOutputVariable &GetOutputAtLocation(const std::vector<PixelShaderOutputVariable> &outputVariables,
                                                         unsigned int location)
 {
     for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex)
@@ -85,15 +88,12 @@ const rx::PixelShaderOutputVariable &GetOutputAtLocation(const std::vector<rx::P
     return outputVariables[0];
 }
 
-}
-
-namespace rx
-{
-
 const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
 const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@";
 
-DynamicHLSL::DynamicHLSL(rx::Renderer *const renderer)
+}
+
+DynamicHLSL::DynamicHLSL(RendererD3D *const renderer)
     : mRenderer(renderer)
 {
 }
@@ -225,8 +225,8 @@ static bool packVarying(PackedVarying *varying, const int maxVaryingVectors, Var
 
 // Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
 // Returns the number of used varying registers, or -1 if unsuccesful
-int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, rx::ShaderD3D *fragmentShader,
-                              rx::ShaderD3D *vertexShader, const std::vector<std::string>& transformFeedbackVaryings)
+int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, ShaderD3D *fragmentShader,
+                              ShaderD3D *vertexShader, const std::vector<std::string> &transformFeedbackVaryings)
 {
     // TODO (geofflang):  Use context's caps
     const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors;
@@ -262,6 +262,13 @@ int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, rx::Shad
     for (unsigned int feedbackVaryingIndex = 0; feedbackVaryingIndex < transformFeedbackVaryings.size(); feedbackVaryingIndex++)
     {
         const std::string &transformFeedbackVarying = transformFeedbackVaryings[feedbackVaryingIndex];
+
+        if (transformFeedbackVarying == "gl_Position" || transformFeedbackVarying == "gl_PointSize")
+        {
+            // do not pack builtin XFB varyings
+            continue;
+        }
+
         if (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end())
         {
             bool found = false;
@@ -281,7 +288,7 @@ int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, rx::Shad
                 }
             }
 
-            if (!found && transformFeedbackVarying != "gl_Position" && transformFeedbackVarying != "gl_PointSize")
+            if (!found)
             {
                 infoLog.append("Transform feedback varying %s does not exist in the vertex shader.", transformFeedbackVarying.c_str());
                 return -1;
@@ -400,7 +407,7 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s
             // data reinterpretation (eg for pure integer->float, float->pure integer)
             // TODO: issue warning with gl debug info extension, when supported
             if (IsMatrixType(shaderAttribute.type) ||
-                (mRenderer->getVertexConversionType(vertexFormat) & rx::VERTEX_CONVERT_GPU) != 0)
+                (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_GPU) != 0)
             {
                 initHLSL += generateAttributeConversionHLSL(vertexFormat, shaderAttribute);
             }
@@ -639,7 +646,7 @@ void DynamicHLSL::storeBuiltinLinkedVaryings(const SemanticInfo &info,
     }
 }
 
-void DynamicHLSL::storeUserLinkedVaryings(const rx::ShaderD3D *vertexShader,
+void DynamicHLSL::storeUserLinkedVaryings(const ShaderD3D *vertexShader,
                                           std::vector<LinkedVarying> *linkedVaryings) const
 {
     const std::string &varyingSemantic = getVaryingSemantic(vertexShader->mUsesPointSize);
@@ -662,10 +669,11 @@ void DynamicHLSL::storeUserLinkedVaryings(const rx::ShaderD3D *vertexShader,
     }
 }
 
-bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const VaryingPacking packing,
-                                         std::string& pixelHLSL, std::string& vertexHLSL,
-                                         rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader,
-                                         const std::vector<std::string>& transformFeedbackVaryings,
+bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, int registers,
+                                         const VaryingPacking packing,
+                                         std::string &pixelHLSL, std::string &vertexHLSL,
+                                         ShaderD3D *fragmentShader, ShaderD3D *vertexShader,
+                                         const std::vector<std::string> &transformFeedbackVaryings,
                                          std::vector<LinkedVarying> *linkedVaryings,
                                          std::map<int, VariableLocation> *programOutputVars,
                                          std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
@@ -691,21 +699,17 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
 
     // Write the HLSL input/output declarations
     const int shaderModel = mRenderer->getMajorShaderModel();
-
-    // TODO (geofflang):  Use context's caps
-    const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors;
-
     const int registersNeeded = registers + (usesFragCoord ? 1 : 0) + (usesPointCoord ? 1 : 0);
 
     // Two cases when writing to gl_FragColor and using ESSL 1.0:
     // - with a 3.0 context, the output color is copied to channel 0
     // - with a 2.0 context, the output color is broadcast to all channels
-    const bool broadcast = (fragmentShader->mUsesFragColor && mRenderer->getCurrentClientVersion() < 3);
-    const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getRendererCaps().maxDrawBuffers : 1);
+    const bool broadcast = (fragmentShader->mUsesFragColor && data.clientVersion < 3);
+    const unsigned int numRenderTargets = (broadcast || usesMRT ? data.caps->maxDrawBuffers : 1);
 
     int shaderVersion = vertexShader->getShaderVersion();
 
-    if (registersNeeded > maxVaryingVectors)
+    if (static_cast<GLuint>(registersNeeded) > data.caps->maxVaryingVectors)
     {
         infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
         return false;
@@ -772,7 +776,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
 
                 for (int row = 0; row < variableRows; row++)
                 {
-                    int r = varying.registerIndex + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + elementIndex * variableRows + row;
+                    int r = varying.registerIndex + varying.columnIndex * data.caps->maxVaryingVectors + elementIndex * variableRows + row;
                     vertexHLSL += "    output.v" + Str(r);
 
                     vertexHLSL += " = _" + varying.name;
@@ -920,7 +924,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
                 int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType));
                 for (int row = 0; row < variableRows; row++)
                 {
-                    std::string n = Str(varying.registerIndex + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + elementIndex * variableRows + row);
+                    std::string n = Str(varying.registerIndex + varying.columnIndex * data.caps->maxVaryingVectors + elementIndex * variableRows + row);
                     pixelHLSL += "    _" + varying.name;
 
                     if (varying.isArray())
@@ -966,7 +970,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
     return true;
 }
 
-void DynamicHLSL::defineOutputVariables(rx::ShaderD3D *fragmentShader, std::map<int, VariableLocation> *programOutputVars) const
+void DynamicHLSL::defineOutputVariables(ShaderD3D *fragmentShader, std::map<int, VariableLocation> *programOutputVars) const
 {
     const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getActiveOutputVariables();
 
@@ -994,14 +998,14 @@ void DynamicHLSL::defineOutputVariables(rx::ShaderD3D *fragmentShader, std::map<
     }
 }
 
-std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const
+std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const
 {
     // for now we only handle point sprite emulation
     ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4);
     return generatePointSpriteHLSL(registers, fragmentShader, vertexShader);
 }
 
-std::string DynamicHLSL::generatePointSpriteHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const
+std::string DynamicHLSL::generatePointSpriteHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const
 {
     ASSERT(registers >= 0);
     ASSERT(vertexShader->mUsesPointSize);
@@ -1047,7 +1051,7 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, rx::ShaderD3D *f
                   "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n"
                   "{\n"
                   "    GS_OUTPUT output = (GS_OUTPUT)0;\n"
-                  "    output.gl_Position = input[0].gl_Position;\n";
+                  "    output.gl_Position = input[0].gl_Position;\n"
                   "    output.gl_PointSize = input[0].gl_PointSize;\n";
 
     for (int r = 0; r < registers; r++)
@@ -1135,7 +1139,7 @@ void DynamicHLSL::getInputLayoutSignature(const VertexFormat inputLayout[], GLen
         }
         else
         {
-            bool gpuConverted = ((mRenderer->getVertexConversionType(vertexFormat) & rx::VERTEX_CONVERT_GPU) != 0);
+            bool gpuConverted = ((mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_GPU) != 0);
             signature[inputIndex] = (gpuConverted ? GL_TRUE : GL_FALSE);
         }
     }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h
index f68ed984012..c46bbf6ce01 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h
@@ -10,18 +10,13 @@
 #define LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_
 
 #include "common/angleutils.h"
-#include "libGLESv2/constants.h"
+#include "libGLESv2/Constants.h"
 
 #include "angle_gl.h"
 
 #include <vector>
 #include <map>
 
-namespace rx
-{
-class Renderer;
-}
-
 namespace sh
 {
 struct Attribute;
@@ -36,11 +31,12 @@ struct LinkedVarying;
 struct VertexAttribute;
 struct VertexFormat;
 struct PackedVarying;
+struct Data;
 }
 
 namespace rx
 {
-class Renderer;
+class RendererD3D;
 class ShaderD3D;
 
 typedef const gl::PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4];
@@ -56,30 +52,31 @@ struct PixelShaderOutputVariable
 class DynamicHLSL
 {
   public:
-    explicit DynamicHLSL(rx::Renderer *const renderer);
+    explicit DynamicHLSL(RendererD3D *const renderer);
 
-    int packVaryings(gl::InfoLog &infoLog, VaryingPacking packing, rx::ShaderD3D *fragmentShader,
-                     rx::ShaderD3D *vertexShader, const std::vector<std::string>& transformFeedbackVaryings);
+    int packVaryings(gl::InfoLog &infoLog, VaryingPacking packing, ShaderD3D *fragmentShader,
+                     ShaderD3D *vertexShader, const std::vector<std::string>& transformFeedbackVaryings);
     std::string generateVertexShaderForInputLayout(const std::string &sourceShader, const gl::VertexFormat inputLayout[],
                                                    const sh::Attribute shaderAttributes[]) const;
     std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOutputVariable> &outputVariables,
                                                       bool usesFragDepth, const std::vector<GLenum> &outputLayout) const;
-    bool generateShaderLinkHLSL(gl::InfoLog &infoLog, int registers, const VaryingPacking packing,
-                                std::string& pixelHLSL, std::string& vertexHLSL,
-                                rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader,
-                                const std::vector<std::string>& transformFeedbackVaryings,
+    bool generateShaderLinkHLSL(const gl::Data &data, gl::InfoLog &infoLog, int registers,
+                                const VaryingPacking packing,
+                                std::string &pixelHLSL, std::string &vertexHLSL,
+                                ShaderD3D *fragmentShader, ShaderD3D *vertexShader,
+                                const std::vector<std::string> &transformFeedbackVaryings,
                                 std::vector<gl::LinkedVarying> *linkedVaryings,
                                 std::map<int, gl::VariableLocation> *programOutputVars,
                                 std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
                                 bool *outUsesFragDepth) const;
 
-    std::string generateGeometryShaderHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const;
+    std::string generateGeometryShaderHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const;
     void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(DynamicHLSL);
 
-    rx::Renderer *const mRenderer;
+    RendererD3D *const mRenderer;
 
     struct SemanticInfo;
 
@@ -88,10 +85,10 @@ class DynamicHLSL
                                         bool pixelShader) const;
     std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const;
     std::string generateVaryingHLSL(const ShaderD3D *shader) const;
-    void storeUserLinkedVaryings(const rx::ShaderD3D *vertexShader, std::vector<gl::LinkedVarying> *linkedVaryings) const;
+    void storeUserLinkedVaryings(const ShaderD3D *vertexShader, std::vector<gl::LinkedVarying> *linkedVaryings) const;
     void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector<gl::LinkedVarying> *linkedVaryings) const;
-    void defineOutputVariables(rx::ShaderD3D *fragmentShader, std::map<int, gl::VariableLocation> *programOutputVars) const;
-    std::string generatePointSpriteHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const;
+    void defineOutputVariables(ShaderD3D *fragmentShader, std::map<int, gl::VariableLocation> *programOutputVars) const;
+    std::string generatePointSpriteHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const;
 
     // Prepend an underscore
     static std::string decorateVariable(const std::string &name);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
index d0131974eef..776d92b2028 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
@@ -8,34 +8,116 @@
 #include "libGLESv2/Program.h"
 #include "libGLESv2/main.h"
 
+#include "common/features.h"
 #include "common/utilities.h"
-#include "common/platform.h"
 
-#if defined(__MINGW32__) && !defined(D3DCOMPILER_DLL)
+#ifndef QT_D3DCOMPILER_DLL
+#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL
+#endif
+#ifndef D3DCOMPILE_RESERVED16
+#define D3DCOMPILE_RESERVED16 (1 << 16)
+#endif
+#ifndef D3DCOMPILE_RESERVED17
+#define D3DCOMPILE_RESERVED17 (1 << 17)
+#endif
 
-// Add define + typedefs for older MinGW-w64 headers (pre 5783)
+// Definitions local to the translation unit
+namespace
+{
 
-#define D3DCOMPILER_DLL L"d3dcompiler_43.dll"
+#ifdef CREATE_COMPILER_FLAG_INFO
+    #undef CREATE_COMPILER_FLAG_INFO
+#endif
 
-HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename,
-        const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
-        const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages);
-typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const char *filename,
-        const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
-        const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages);
+#define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag }
 
-#endif // __MINGW32__ && !D3DCOMPILER_DLL
+struct CompilerFlagInfo
+{
+    UINT mFlag;
+    const char *mName;
+};
 
-#ifndef QT_D3DCOMPILER_DLL
-#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL
-#endif
+CompilerFlagInfo CompilerFlagInfos[] =
+{
+    // NOTE: The data below is copied from d3dcompiler.h
+    // If something changes there it should be changed here as well
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_DEBUG),                          // (1 << 0)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_VALIDATION),                // (1 << 1)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_OPTIMIZATION),              // (1 << 2)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_ROW_MAJOR),          // (1 << 3)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR),       // (1 << 4)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PARTIAL_PRECISION),              // (1 << 5)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_VS_SOFTWARE_NO_OPT),       // (1 << 6)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_PS_SOFTWARE_NO_OPT),       // (1 << 7)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_NO_PRESHADER),                   // (1 << 8)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_AVOID_FLOW_CONTROL),             // (1 << 9)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PREFER_FLOW_CONTROL),            // (1 << 10)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_STRICTNESS),              // (1 << 11)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY), // (1 << 12)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_IEEE_STRICTNESS),                // (1 << 13)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL0),            // (1 << 14)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL1),            // 0
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL2),            // ((1 << 14) | (1 << 15))
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL3),            // (1 << 15)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED16),                     // (1 << 16)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED17),                     // (1 << 17)
+    CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_WARNINGS_ARE_ERRORS)             // (1 << 18)
+};
+
+#undef CREATE_COMPILER_FLAG_INFO
+
+bool IsCompilerFlagSet(UINT mask, UINT flag)
+{
+    bool isFlagSet = IsMaskFlagSet(mask, flag);
+
+    switch(flag)
+    {
+      case D3DCOMPILE_OPTIMIZATION_LEVEL0:
+        return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL3));
+
+      case D3DCOMPILE_OPTIMIZATION_LEVEL1:
+        return (mask & D3DCOMPILE_OPTIMIZATION_LEVEL2) == UINT(0);
+
+      case D3DCOMPILE_OPTIMIZATION_LEVEL3:
+        return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL0));
+
+      default:
+        return isFlagSet;
+    }
+}
+
+const char *GetCompilerFlagName(UINT mask, size_t flagIx)
+{
+    const CompilerFlagInfo &flagInfo = CompilerFlagInfos[flagIx];
+    if (IsCompilerFlagSet(mask, flagInfo.mFlag))
+    {
+        return flagInfo.mName;
+    }
+
+    return nullptr;
+}
+
+}
 
 namespace rx
 {
 
+CompileConfig::CompileConfig()
+    : flags(0),
+      name()
+{
+}
+
+CompileConfig::CompileConfig(UINT flags, const std::string &name)
+    : flags(flags),
+      name(name)
+{
+}
+
 HLSLCompiler::HLSLCompiler()
     : mD3DCompilerModule(NULL),
-      mD3DCompileFunc(NULL)
+      mD3DCompileFunc(NULL),
+      mD3DDisassembleFunc(NULL)
 {
 }
 
@@ -46,7 +128,7 @@ HLSLCompiler::~HLSLCompiler()
 
 bool HLSLCompiler::initialize()
 {
-#if !defined(ANGLE_PLATFORM_WINRT)
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
 #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
     // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
     static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
@@ -83,17 +165,32 @@ bool HLSLCompiler::initialize()
             break;
     }
 
+    if (!mD3DCompilerModule)
+    {
+        // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
+        mD3DCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
+    }
+
     if (!mD3DCompilerModule)
     {
         ERR("No D3D compiler module found - aborting!\n");
         return false;
     }
 
-    mD3DCompileFunc = reinterpret_cast<CompileFuncPtr>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
+    mD3DCompileFunc = reinterpret_cast<pD3DCompile>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
     ASSERT(mD3DCompileFunc);
+
+    mD3DDisassembleFunc = reinterpret_cast<pD3DDisassemble>(GetProcAddress(mD3DCompilerModule, "D3DDisassemble"));
+    ASSERT(mD3DDisassembleFunc);
+
 #else
-    mD3DCompileFunc = reinterpret_cast<CompileFuncPtr>(&D3DCompile);
+    // D3D Shader compiler is linked already into this module, so the export
+    // can be directly assigned.
+    mD3DCompilerModule = NULL;
+    mD3DCompileFunc = reinterpret_cast<pD3DCompile>(D3DCompile);
+    mD3DDisassembleFunc = reinterpret_cast<pD3DDisassemble>(D3DDisassemble);
 #endif
+
     return mD3DCompileFunc != NULL;
 }
 
@@ -104,61 +201,133 @@ void HLSLCompiler::release()
         FreeLibrary(mD3DCompilerModule);
         mD3DCompilerModule = NULL;
         mD3DCompileFunc = NULL;
+        mD3DDisassembleFunc = NULL;
     }
 }
 
-ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile,
-                                          const UINT optimizationFlags[], const char *flagNames[], int attempts) const
+gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
+                                        const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros,
+                                        ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const
 {
-#if !defined(ANGLE_PLATFORM_WINRT)
-    ASSERT(mD3DCompilerModule && mD3DCompileFunc);
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+    ASSERT(mD3DCompilerModule);
 #endif
+    ASSERT(mD3DCompileFunc);
 
-    if (!hlsl)
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+    if (gl::perfActive())
     {
-        return NULL;
+        std::string sourcePath = getTempPath();
+        std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str());
+        writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
     }
+#endif
+
+    const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : NULL;
 
-    pD3DCompile compileFunc = reinterpret_cast<pD3DCompile>(mD3DCompileFunc);
-    for (int i = 0; i < attempts; ++i)
+    for (size_t i = 0; i < configs.size(); ++i)
     {
         ID3DBlob *errorMessage = NULL;
         ID3DBlob *binary = NULL;
 
-        HRESULT result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL, "main", profile, optimizationFlags[i], 0, &binary, &errorMessage);
+        HRESULT result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, NULL, "main", profile.c_str(),
+                                         configs[i].flags, 0, &binary, &errorMessage);
 
         if (errorMessage)
         {
-            const char *message = (const char*)errorMessage->GetBufferPointer();
+            std::string message = reinterpret_cast<const char*>(errorMessage->GetBufferPointer());
+            SafeRelease(errorMessage);
 
-            infoLog.appendSanitized(message);
-            TRACE("\n%s", hlsl);
-            TRACE("\n%s", message);
+            infoLog.appendSanitized(message.c_str());
+            TRACE("\n%s", hlsl.c_str());
+            TRACE("\n%s", message.c_str());
 
-            SafeRelease(errorMessage);
+            if (message.find("error X3531:") != std::string::npos)   // "can't unroll loops marked with loop attribute"
+            {
+                macros = NULL;   // Disable [loop] and [flatten]
+
+                // Retry without changing compiler flags
+                i--;
+                continue;
+            }
         }
 
         if (SUCCEEDED(result))
         {
-            return (ShaderBlob*)binary;
+            *outCompiledBlob = binary;
+
+#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
+            (*outDebugInfo) += "// COMPILER INPUT HLSL BEGIN\n\n" + hlsl + "\n// COMPILER INPUT HLSL END\n";
+            (*outDebugInfo) += "\n\n// ASSEMBLY BEGIN\n\n";
+            (*outDebugInfo) += "// Compiler configuration: " + configs[i].name + "\n// Flags:\n";
+            for (size_t fIx = 0; fIx < ArraySize(CompilerFlagInfos); ++fIx)
+            {
+                const char *flagName = GetCompilerFlagName(configs[i].flags, fIx);
+                if (flagName != nullptr)
+                {
+                    (*outDebugInfo) += std::string("// ") + flagName + "\n";
+                }
+            }
+
+            (*outDebugInfo) += "// Macros:\n";
+            if (macros == nullptr)
+            {
+                (*outDebugInfo) += "// - : -\n";
+            }
+            else
+            {
+                for (const D3D_SHADER_MACRO *mIt = macros; mIt->Name != nullptr; ++mIt)
+                {
+                    (*outDebugInfo) += std::string("// ") + mIt->Name + " : " + mIt->Definition + "\n";
+                }
+            }
+
+            (*outDebugInfo) += "\n" + disassembleBinary(binary) + "\n// ASSEMBLY END\n";
+#endif
+
+            return gl::Error(GL_NO_ERROR);
         }
         else
         {
             if (result == E_OUTOFMEMORY)
             {
-                return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*)NULL);
+                *outCompiledBlob = NULL;
+                return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result);
             }
 
-            infoLog.append("Warning: D3D shader compilation failed with %s flags.", flagNames[i]);
+            infoLog.append("Warning: D3D shader compilation failed with %s flags.", configs[i].name.c_str());
 
-            if (i + 1 < attempts)
+            if (i + 1 < configs.size())
             {
-                infoLog.append(" Retrying with %s.\n", flagNames[i + 1]);
+                infoLog.append(" Retrying with %s.\n", configs[i + 1].name.c_str());
             }
         }
     }
 
-    return NULL;
+    // None of the configurations succeeded in compiling this shader but the compiler is still intact
+    *outCompiledBlob = NULL;
+    return gl::Error(GL_NO_ERROR);
+}
+
+std::string HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary) const
+{
+    // Retrieve disassembly
+    UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING;
+    ID3DBlob *disassembly = NULL;
+    pD3DDisassemble disassembleFunc = reinterpret_cast<pD3DDisassemble>(mD3DDisassembleFunc);
+    LPCVOID buffer = shaderBinary->GetBufferPointer();
+    SIZE_T bufSize = shaderBinary->GetBufferSize();
+    HRESULT result = disassembleFunc(buffer, bufSize, flags, "", &disassembly);
+
+    std::string asmSrc;
+    if (SUCCEEDED(result))
+    {
+        asmSrc = reinterpret_cast<const char*>(disassembly->GetBufferPointer());
+    }
+
+    SafeRelease(disassembly);
+
+    return asmSrc;
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h
index 0ce9e44be54..ff56f8035a7 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h
@@ -1,7 +1,13 @@
 #ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
 #define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
 
+#include "libGLESv2/Error.h"
+
 #include "common/angleutils.h"
+#include "common/platform.h"
+
+#include <vector>
+#include <string>
 
 namespace gl
 {
@@ -11,8 +17,14 @@ class InfoLog;
 namespace rx
 {
 
-typedef void* ShaderBlob;
-typedef void(*CompileFuncPtr)();
+struct CompileConfig
+{
+    UINT flags;
+    std::string name;
+
+    CompileConfig();
+    CompileConfig(UINT flags, const std::string &name);
+};
 
 class HLSLCompiler
 {
@@ -23,14 +35,20 @@ class HLSLCompiler
     bool initialize();
     void release();
 
-    ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile,
-                                const UINT optimizationFlags[], const char *flagNames[], int attempts) const;
+    // Attempt to compile a HLSL shader using the supplied configurations, may output a NULL compiled blob
+    // even if no GL errors are returned.
+    gl::Error compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
+                              const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros,
+                              ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const;
+
+    std::string disassembleBinary(ID3DBlob* shaderBinary) const;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(HLSLCompiler);
 
     HMODULE mD3DCompilerModule;
-    CompileFuncPtr mD3DCompileFunc;
+    pD3DCompile mD3DCompileFunc;
+    pD3DDisassemble mD3DDisassembleFunc;
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp
index 0854b968da6..12b919ab5a1 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp
@@ -19,8 +19,8 @@ ImageD3D::ImageD3D()
 
 ImageD3D *ImageD3D::makeImageD3D(Image *img)
 {
-    ASSERT(HAS_DYNAMIC_TYPE(rx::ImageD3D*, img));
-    return static_cast<rx::ImageD3D*>(img);
+    ASSERT(HAS_DYNAMIC_TYPE(ImageD3D*, img));
+    return static_cast<ImageD3D*>(img);
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h
index 60a6ffdf37e..554ca0cee04 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h
@@ -17,6 +17,8 @@
 namespace gl
 {
 class Framebuffer;
+struct ImageIndex;
+struct Box;
 }
 
 namespace rx
@@ -33,14 +35,11 @@ class ImageD3D : public Image
 
     virtual bool isDirty() const = 0;
 
-    virtual void setManagedSurface2D(TextureStorage *storage, int level) {};
-    virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level) {};
-    virtual void setManagedSurface3D(TextureStorage *storage, int level) {};
-    virtual void setManagedSurface2DArray(TextureStorage *storage, int layer, int level) {};
-    virtual bool copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
-    virtual bool copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0;
-    virtual bool copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) = 0;
-    virtual bool copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) = 0;
+    virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); };
+    virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level) { return gl::Error(GL_NO_ERROR); };
+    virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); };
+    virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level) { return gl::Error(GL_NO_ERROR); };
+    virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(ImageD3D);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp
index 1dce1270d8e..aa614f6cc41 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp
@@ -8,7 +8,7 @@
 // class with derivations, classes that perform graphics API agnostic index buffer operations.
 
 #include "libGLESv2/renderer/d3d/IndexBuffer.h"
-#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
 
 namespace rx
 {
@@ -35,7 +35,7 @@ void IndexBuffer::updateSerial()
 }
 
 
-IndexBufferInterface::IndexBufferInterface(Renderer *renderer, bool dynamic) : mRenderer(renderer)
+IndexBufferInterface::IndexBufferInterface(RendererD3D *renderer, bool dynamic) : mRenderer(renderer)
 {
     mIndexBuffer = renderer->createIndexBuffer();
 
@@ -130,7 +130,7 @@ gl::Error IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum in
     }
 }
 
-StreamingIndexBufferInterface::StreamingIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, true)
+StreamingIndexBufferInterface::StreamingIndexBufferInterface(RendererD3D *renderer) : IndexBufferInterface(renderer, true)
 {
 }
 
@@ -165,7 +165,7 @@ gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, G
 }
 
 
-StaticIndexBufferInterface::StaticIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, false)
+StaticIndexBufferInterface::StaticIndexBufferInterface(RendererD3D *renderer) : IndexBufferInterface(renderer, false)
 {
 }
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h
index 1bb5ae2c4a2..a34d30bbf37 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h
@@ -16,7 +16,7 @@
 
 namespace rx
 {
-class Renderer;
+class RendererD3D;
 
 class IndexBuffer
 {
@@ -50,7 +50,7 @@ class IndexBuffer
 class IndexBufferInterface
 {
   public:
-    IndexBufferInterface(Renderer *renderer, bool dynamic);
+    IndexBufferInterface(RendererD3D *renderer, bool dynamic);
     virtual ~IndexBufferInterface();
 
     virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) = 0;
@@ -76,7 +76,7 @@ class IndexBufferInterface
   private:
     DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface);
 
-    rx::Renderer *const mRenderer;
+    RendererD3D *const mRenderer;
 
     IndexBuffer* mIndexBuffer;
 
@@ -87,7 +87,7 @@ class IndexBufferInterface
 class StreamingIndexBufferInterface : public IndexBufferInterface
 {
   public:
-    StreamingIndexBufferInterface(Renderer *renderer);
+    StreamingIndexBufferInterface(RendererD3D *renderer);
     ~StreamingIndexBufferInterface();
 
     virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType);
@@ -96,7 +96,7 @@ class StreamingIndexBufferInterface : public IndexBufferInterface
 class StaticIndexBufferInterface : public IndexBufferInterface
 {
   public:
-    explicit StaticIndexBufferInterface(Renderer *renderer);
+    explicit StaticIndexBufferInterface(RendererD3D *renderer);
     ~StaticIndexBufferInterface();
 
     virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp
index 8d455b4bf3e..eddd9de8873 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp
@@ -10,7 +10,7 @@
 #include "libGLESv2/renderer/d3d/IndexDataManager.h"
 #include "libGLESv2/renderer/d3d/BufferD3D.h"
 #include "libGLESv2/renderer/d3d/IndexBuffer.h"
-#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
 #include "libGLESv2/Buffer.h"
 #include "libGLESv2/main.h"
 #include "libGLESv2/formatutils.h"
@@ -57,7 +57,7 @@ static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void
     else UNREACHABLE();
 }
 
-IndexDataManager::IndexDataManager(Renderer *renderer)
+IndexDataManager::IndexDataManager(RendererD3D *renderer)
     : mRenderer(renderer),
       mStreamingBufferShort(NULL),
       mStreamingBufferInt(NULL)
@@ -97,7 +97,14 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf
 
         ASSERT(typeInfo.bytes * static_cast<unsigned int>(count) + offset <= storage->getSize());
 
-        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+        const uint8_t *bufferData = NULL;
+        gl::Error error = storage->getData(&bufferData);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        indices = bufferData + offset;
     }
 
     StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL;
@@ -183,7 +190,16 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf
             return error;
         }
 
-        ConvertIndices(type, destinationIndexType, staticBuffer ? storage->getData() : indices, convertCount, output);
+        const uint8_t *dataPointer = reinterpret_cast<const uint8_t*>(indices);
+        if (staticBuffer)
+        {
+            error = storage->getData(&dataPointer);
+            if (error.isError())
+            {
+                return error;
+            }
+        }
+        ConvertIndices(type, destinationIndexType, dataPointer, convertCount, output);
 
         error = indexBuffer->unmapBuffer();
         if (error.isError())
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h
index 6d0b89e6d4a..a1aee1588b0 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h
@@ -33,7 +33,7 @@ class StaticIndexBufferInterface;
 class StreamingIndexBufferInterface;
 class IndexBuffer;
 class BufferD3D;
-class Renderer;
+class RendererD3D;
 
 struct TranslatedIndexData
 {
@@ -50,7 +50,7 @@ struct TranslatedIndexData
 class IndexDataManager
 {
   public:
-    explicit IndexDataManager(Renderer *renderer);
+    explicit IndexDataManager(RendererD3D *renderer);
     virtual ~IndexDataManager();
 
     gl::Error prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated);
@@ -60,7 +60,7 @@ class IndexDataManager
 
     DISALLOW_COPY_AND_ASSIGN(IndexDataManager);
 
-    Renderer *const mRenderer;
+    RendererD3D *const mRenderer;
 
     StreamingIndexBufferInterface *mStreamingBufferShort;
     StreamingIndexBufferInterface *mStreamingBufferInt;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp
index d7d97cc2bd2..75da78110e7 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp
@@ -8,27 +8,163 @@
 
 #include "libGLESv2/renderer/d3d/ProgramD3D.h"
 
+#include "common/features.h"
 #include "common/utilities.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
+#include "libGLESv2/Program.h"
 #include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/main.h"
 #include "libGLESv2/renderer/ShaderExecutable.h"
 #include "libGLESv2/renderer/d3d/DynamicHLSL.h"
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
 #include "libGLESv2/renderer/d3d/ShaderD3D.h"
-#include "libGLESv2/main.h"
 
 namespace rx
 {
 
-ProgramD3D::ProgramD3D(rx::Renderer *renderer)
+namespace
+{
+
+GLenum GetTextureType(GLenum samplerType)
+{
+    switch (samplerType)
+    {
+      case GL_SAMPLER_2D:
+      case GL_INT_SAMPLER_2D:
+      case GL_UNSIGNED_INT_SAMPLER_2D:
+      case GL_SAMPLER_2D_SHADOW:
+        return GL_TEXTURE_2D;
+      case GL_SAMPLER_3D:
+      case GL_INT_SAMPLER_3D:
+      case GL_UNSIGNED_INT_SAMPLER_3D:
+        return GL_TEXTURE_3D;
+      case GL_SAMPLER_CUBE:
+      case GL_SAMPLER_CUBE_SHADOW:
+        return GL_TEXTURE_CUBE_MAP;
+      case GL_INT_SAMPLER_CUBE:
+      case GL_UNSIGNED_INT_SAMPLER_CUBE:
+        return GL_TEXTURE_CUBE_MAP;
+      case GL_SAMPLER_2D_ARRAY:
+      case GL_INT_SAMPLER_2D_ARRAY:
+      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+      case GL_SAMPLER_2D_ARRAY_SHADOW:
+        return GL_TEXTURE_2D_ARRAY;
+      default: UNREACHABLE();
+    }
+
+    return GL_TEXTURE_2D;
+}
+
+void GetDefaultInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS])
+{
+    size_t layoutIndex = 0;
+    for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
+    {
+        ASSERT(layoutIndex < gl::MAX_VERTEX_ATTRIBS);
+
+        const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex];
+
+        if (shaderAttr.type != GL_NONE)
+        {
+            GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
+
+            for (size_t rowIndex = 0; static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); rowIndex++, layoutIndex++)
+            {
+                gl::VertexFormat *defaultFormat = &inputLayout[layoutIndex];
+
+                defaultFormat->mType = gl::VariableComponentType(transposedType);
+                defaultFormat->mNormalized = false;
+                defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool
+                defaultFormat->mComponents = gl::VariableColumnCount(transposedType);
+            }
+        }
+    }
+}
+
+std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
+{
+    std::vector<GLenum> defaultPixelOutput(1);
+
+    ASSERT(!shaderOutputVars.empty());
+    defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex;
+
+    return defaultPixelOutput;
+}
+
+bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
+{
+    return var.isRowMajorLayout;
+}
+
+bool IsRowMajorLayout(const sh::ShaderVariable &var)
+{
+    return false;
+}
+
+}
+
+ProgramD3D::VertexExecutable::VertexExecutable(const gl::VertexFormat inputLayout[],
+                                               const GLenum signature[],
+                                               ShaderExecutable *shaderExecutable)
+    : mShaderExecutable(shaderExecutable)
+{
+    for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        mInputs[attributeIndex] = inputLayout[attributeIndex];
+        mSignature[attributeIndex] = signature[attributeIndex];
+    }
+}
+
+ProgramD3D::VertexExecutable::~VertexExecutable()
+{
+    SafeDelete(mShaderExecutable);
+}
+
+bool ProgramD3D::VertexExecutable::matchesSignature(const GLenum signature[]) const
+{
+    for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
+    {
+        if (mSignature[attributeIndex] != signature[attributeIndex])
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutable *shaderExecutable)
+    : mOutputSignature(outputSignature),
+      mShaderExecutable(shaderExecutable)
+{
+}
+
+ProgramD3D::PixelExecutable::~PixelExecutable()
+{
+    SafeDelete(mShaderExecutable);
+}
+
+ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
+{
+}
+
+ProgramD3D::ProgramD3D(RendererD3D *renderer)
     : ProgramImpl(),
       mRenderer(renderer),
       mDynamicHLSL(NULL),
-      mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
-      mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
+      mGeometryExecutable(NULL),
+      mVertexWorkarounds(ANGLE_D3D_WORKAROUND_NONE),
+      mPixelWorkarounds(ANGLE_D3D_WORKAROUND_NONE),
+      mUsesPointSize(false),
       mVertexUniformStorage(NULL),
-      mFragmentUniformStorage(NULL)
+      mFragmentUniformStorage(NULL),
+      mUsedVertexSamplerRange(0),
+      mUsedPixelSamplerRange(0),
+      mDirtySamplerMapping(true),
+      mShaderVersion(100)
 {
-    mDynamicHLSL = new rx::DynamicHLSL(renderer);
+    mDynamicHLSL = new DynamicHLSL(renderer);
 }
 
 ProgramD3D::~ProgramD3D()
@@ -49,157 +185,1741 @@ const ProgramD3D *ProgramD3D::makeProgramD3D(const ProgramImpl *impl)
     return static_cast<const ProgramD3D*>(impl);
 }
 
-bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
+bool ProgramD3D::usesPointSpriteEmulation() const
 {
-    stream->readString(&mVertexHLSL);
-    stream->readInt(&mVertexWorkarounds);
-    stream->readString(&mPixelHLSL);
-    stream->readInt(&mPixelWorkarounds);
-    stream->readBool(&mUsesFragDepth);
+    return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
+}
 
-    const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
-    mPixelShaderKey.resize(pixelShaderKeySize);
-    for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
+bool ProgramD3D::usesGeometryShader() const
+{
+    return usesPointSpriteEmulation();
+}
+
+GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const
+{
+    GLint logicalTextureUnit = -1;
+
+    switch (type)
     {
-        stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
-        stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
-        stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
-        stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
+      case gl::SAMPLER_PIXEL:
+        ASSERT(samplerIndex < caps.maxTextureImageUnits);
+        if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
+        {
+            logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
+        }
+        break;
+      case gl::SAMPLER_VERTEX:
+        ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
+        if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
+        {
+            logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
+        }
+        break;
+      default: UNREACHABLE();
     }
 
-    return true;
+    if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
+    {
+        return logicalTextureUnit;
+    }
+
+    return -1;
 }
 
-bool ProgramD3D::save(gl::BinaryOutputStream *stream)
+// Returns the texture type for a given Direct3D 9 sampler type and
+// index (0-15 for the pixel shader and 0-3 for the vertex shader).
+GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const
 {
-    stream->writeString(mVertexHLSL);
-    stream->writeInt(mVertexWorkarounds);
-    stream->writeString(mPixelHLSL);
-    stream->writeInt(mPixelWorkarounds);
-    stream->writeInt(mUsesFragDepth);
-
-    const std::vector<rx::PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
-    stream->writeInt(pixelShaderKey.size());
-    for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
+    switch (type)
     {
-        const rx::PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
-        stream->writeInt(variable.type);
-        stream->writeString(variable.name);
-        stream->writeString(variable.source);
-        stream->writeInt(variable.outputIndex);
+      case gl::SAMPLER_PIXEL:
+        ASSERT(samplerIndex < mSamplersPS.size());
+        ASSERT(mSamplersPS[samplerIndex].active);
+        return mSamplersPS[samplerIndex].textureType;
+      case gl::SAMPLER_VERTEX:
+        ASSERT(samplerIndex < mSamplersVS.size());
+        ASSERT(mSamplersVS[samplerIndex].active);
+        return mSamplersVS[samplerIndex].textureType;
+      default: UNREACHABLE();
     }
 
-    return true;
+    return GL_TEXTURE_2D;
 }
 
-rx::ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector<GLenum> &outputSignature,
-                                                                    const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
-                                                                    bool separatedOutputBuffers)
+GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
 {
-    std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
-                                                                                     outputSignature);
+    switch (type)
+    {
+      case gl::SAMPLER_PIXEL:
+        return mUsedPixelSamplerRange;
+      case gl::SAMPLER_VERTEX:
+        return mUsedVertexSamplerRange;
+      default:
+        UNREACHABLE();
+        return 0;
+    }
+}
 
-    // Generate new pixel executable
-    rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(infoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL,
-                                                                           transformFeedbackLinkedVaryings, separatedOutputBuffers,
-                                                                           mPixelWorkarounds);
+void ProgramD3D::updateSamplerMapping()
+{
+    if (!mDirtySamplerMapping)
+    {
+        return;
+    }
+
+    mDirtySamplerMapping = false;
+
+    // Retrieve sampler uniform values
+    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+    {
+        gl::LinkedUniform *targetUniform = mUniforms[uniformIndex];
+
+        if (targetUniform->dirty)
+        {
+            if (gl::IsSampler(targetUniform->type))
+            {
+                int count = targetUniform->elementCount();
+                GLint (*v)[4] = reinterpret_cast<GLint(*)[4]>(targetUniform->data);
+
+                if (targetUniform->isReferencedByFragmentShader())
+                {
+                    unsigned int firstIndex = targetUniform->psRegisterIndex;
+
+                    for (int i = 0; i < count; i++)
+                    {
+                        unsigned int samplerIndex = firstIndex + i;
+
+                        if (samplerIndex < mSamplersPS.size())
+                        {
+                            ASSERT(mSamplersPS[samplerIndex].active);
+                            mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
+                        }
+                    }
+                }
+
+                if (targetUniform->isReferencedByVertexShader())
+                {
+                    unsigned int firstIndex = targetUniform->vsRegisterIndex;
 
-    return pixelExecutable;
+                    for (int i = 0; i < count; i++)
+                    {
+                        unsigned int samplerIndex = firstIndex + i;
+
+                        if (samplerIndex < mSamplersVS.size())
+                        {
+                            ASSERT(mSamplersVS[samplerIndex].active);
+                            mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
+                        }
+                    }
+                }
+            }
+        }
+    }
 }
 
-rx::ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(gl::InfoLog &infoLog,
-                                                                    const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
-                                                                    const sh::Attribute shaderAttributes[],
-                                                                    const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
-                                                                    bool separatedOutputBuffers)
+bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
 {
-    // Generate new dynamic layout with attribute conversions
-    std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, shaderAttributes);
+    // if any two active samplers in a program are of different types, but refer to the same
+    // texture image unit, and this is the current program, then ValidateProgram will fail, and
+    // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
+    updateSamplerMapping();
 
-    // Generate new vertex executable
-    rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(infoLog, finalVertexHLSL.c_str(),
-                                                                            rx::SHADER_VERTEX,
-                                                                            transformFeedbackLinkedVaryings, separatedOutputBuffers,
-                                                                            mVertexWorkarounds);
+    std::vector<GLenum> textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE);
+
+    for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
+    {
+        if (mSamplersPS[i].active)
+        {
+            unsigned int unit = mSamplersPS[i].logicalTextureUnit;
+
+            if (unit >= textureUnitTypes.size())
+            {
+                if (infoLog)
+                {
+                    infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size());
+                }
+
+                return false;
+            }
+
+            if (textureUnitTypes[unit] != GL_NONE)
+            {
+                if (mSamplersPS[i].textureType != textureUnitTypes[unit])
+                {
+                    if (infoLog)
+                    {
+                        infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
+                    }
+
+                    return false;
+                }
+            }
+            else
+            {
+                textureUnitTypes[unit] = mSamplersPS[i].textureType;
+            }
+        }
+    }
+
+    for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
+    {
+        if (mSamplersVS[i].active)
+        {
+            unsigned int unit = mSamplersVS[i].logicalTextureUnit;
 
-    return vertexExecutable;
+            if (unit >= textureUnitTypes.size())
+            {
+                if (infoLog)
+                {
+                    infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size());
+                }
+
+                return false;
+            }
+
+            if (textureUnitTypes[unit] != GL_NONE)
+            {
+                if (mSamplersVS[i].textureType != textureUnitTypes[unit])
+                {
+                    if (infoLog)
+                    {
+                        infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
+                    }
+
+                    return false;
+                }
+            }
+            else
+            {
+                textureUnitTypes[unit] = mSamplersVS[i].textureType;
+            }
+        }
+    }
+
+    return true;
 }
 
-bool ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
-                      const std::vector<std::string> &transformFeedbackVaryings, int *registers,
-                      std::vector<gl::LinkedVarying> *linkedVaryings, std::map<int, gl::VariableLocation> *outputVariables)
+gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
 {
-    rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
-    rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
+    stream->readInt(&mShaderVersion);
 
-    mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
-    mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
+    const unsigned int psSamplerCount = stream->readInt<unsigned int>();
+    for (unsigned int i = 0; i < psSamplerCount; ++i)
+    {
+        Sampler sampler;
+        stream->readBool(&sampler.active);
+        stream->readInt(&sampler.logicalTextureUnit);
+        stream->readInt(&sampler.textureType);
+        mSamplersPS.push_back(sampler);
+    }
+    const unsigned int vsSamplerCount = stream->readInt<unsigned int>();
+    for (unsigned int i = 0; i < vsSamplerCount; ++i)
+    {
+        Sampler sampler;
+        stream->readBool(&sampler.active);
+        stream->readInt(&sampler.logicalTextureUnit);
+        stream->readInt(&sampler.textureType);
+        mSamplersVS.push_back(sampler);
+    }
 
-    mVertexHLSL = vertexShaderD3D->getTranslatedSource();
-    mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
+    stream->readInt(&mUsedVertexSamplerRange);
+    stream->readInt(&mUsedPixelSamplerRange);
 
-    // Map the varyings to the register file
-    rx::VaryingPacking packing = { NULL };
-    *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings);
+    const unsigned int uniformCount = stream->readInt<unsigned int>();
+    if (stream->error())
+    {
+        infoLog.append("Invalid program binary.");
+        return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+    }
 
-    if (*registers < 0)
+    mUniforms.resize(uniformCount);
+    for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
     {
-        return false;
+        GLenum type = stream->readInt<GLenum>();
+        GLenum precision = stream->readInt<GLenum>();
+        std::string name = stream->readString();
+        unsigned int arraySize = stream->readInt<unsigned int>();
+        int blockIndex = stream->readInt<int>();
+
+        int offset = stream->readInt<int>();
+        int arrayStride = stream->readInt<int>();
+        int matrixStride = stream->readInt<int>();
+        bool isRowMajorMatrix = stream->readBool();
+
+        const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix);
+
+        gl::LinkedUniform *uniform = new gl::LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo);
+
+        stream->readInt(&uniform->psRegisterIndex);
+        stream->readInt(&uniform->vsRegisterIndex);
+        stream->readInt(&uniform->registerCount);
+        stream->readInt(&uniform->registerElement);
+
+        mUniforms[uniformIndex] = uniform;
     }
 
-    if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader))
+    const unsigned int uniformIndexCount = stream->readInt<unsigned int>();
+    if (stream->error())
     {
-        return false;
+        infoLog.append("Invalid program binary.");
+        return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
     }
 
-    if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
-                                              fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
-                                              linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
+    mUniformIndex.resize(uniformIndexCount);
+    for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++)
     {
-        return false;
+        stream->readString(&mUniformIndex[uniformIndexIndex].name);
+        stream->readInt(&mUniformIndex[uniformIndexIndex].element);
+        stream->readInt(&mUniformIndex[uniformIndexIndex].index);
     }
 
-    return true;
-}
+    unsigned int uniformBlockCount = stream->readInt<unsigned int>();
+    if (stream->error())
+    {
+        infoLog.append("Invalid program binary.");
+        return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+    }
 
-void ProgramD3D::initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms)
-{
-    // Compute total default block size
-    unsigned int vertexRegisters = 0;
-    unsigned int fragmentRegisters = 0;
-    for (size_t uniformIndex = 0; uniformIndex < uniforms.size(); uniformIndex++)
+    mUniformBlocks.resize(uniformBlockCount);
+    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
     {
-        const gl::LinkedUniform &uniform = *uniforms[uniformIndex];
+        std::string name = stream->readString();
+        unsigned int elementIndex = stream->readInt<unsigned int>();
+        unsigned int dataSize = stream->readInt<unsigned int>();
 
-        if (!gl::IsSampler(uniform.type))
+        gl::UniformBlock *uniformBlock = new gl::UniformBlock(name, elementIndex, dataSize);
+
+        stream->readInt(&uniformBlock->psRegisterIndex);
+        stream->readInt(&uniformBlock->vsRegisterIndex);
+
+        unsigned int numMembers = stream->readInt<unsigned int>();
+        uniformBlock->memberUniformIndexes.resize(numMembers);
+        for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
         {
-            if (uniform.isReferencedByVertexShader())
-            {
-                vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
-            }
-            if (uniform.isReferencedByFragmentShader())
-            {
-                fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
-            }
+            stream->readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]);
         }
+
+        mUniformBlocks[uniformBlockIndex] = uniformBlock;
     }
 
-    mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
-    mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
-}
+    stream->readInt(&mTransformFeedbackBufferMode);
+    const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
+    mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
+    for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
+    {
+        gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
 
-void ProgramD3D::reset()
-{
-    mVertexHLSL.clear();
-    mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
+        stream->readString(&varying.name);
+        stream->readInt(&varying.type);
+        stream->readInt(&varying.size);
+        stream->readString(&varying.semanticName);
+        stream->readInt(&varying.semanticIndex);
+        stream->readInt(&varying.semanticIndexCount);
+    }
 
-    mPixelHLSL.clear();
-    mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
-    mUsesFragDepth = false;
-    mPixelShaderKey.clear();
+    stream->readString(&mVertexHLSL);
+    stream->readInt(&mVertexWorkarounds);
+    stream->readString(&mPixelHLSL);
+    stream->readInt(&mPixelWorkarounds);
+    stream->readBool(&mUsesFragDepth);
+    stream->readBool(&mUsesPointSize);
 
-    SafeDelete(mVertexUniformStorage);
-    SafeDelete(mFragmentUniformStorage);
+    const size_t pixelShaderKeySize = stream->readInt<unsigned int>();
+    mPixelShaderKey.resize(pixelShaderKeySize);
+    for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
+    {
+        stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
+        stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
+        stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
+        stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
+    }
+
+    const unsigned char* binary = reinterpret_cast<const unsigned char*>(stream->data());
+
+    const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
+    for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
+    {
+        gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS];
+
+        for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
+        {
+            gl::VertexFormat *vertexInput = &inputLayout[inputIndex];
+            stream->readInt(&vertexInput->mType);
+            stream->readInt(&vertexInput->mNormalized);
+            stream->readInt(&vertexInput->mComponents);
+            stream->readBool(&vertexInput->mPureInteger);
+        }
+
+        unsigned int vertexShaderSize = stream->readInt<unsigned int>();
+        const unsigned char *vertexShaderFunction = binary + stream->offset();
+
+        ShaderExecutable *shaderExecutable = NULL;
+        gl::Error error = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
+                                                    SHADER_VERTEX,
+                                                    mTransformFeedbackLinkedVaryings,
+                                                    (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
+                                                    &shaderExecutable);
+        if (error.isError())
+        {
+            return gl::LinkResult(false, error);
+        }
+
+        if (!shaderExecutable)
+        {
+            infoLog.append("Could not create vertex shader.");
+            return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+        }
+
+        // generated converted input layout
+        GLenum signature[gl::MAX_VERTEX_ATTRIBS];
+        getInputLayoutSignature(inputLayout, signature);
+
+        // add new binary
+        mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
+
+        stream->skip(vertexShaderSize);
+    }
+
+    const size_t pixelShaderCount = stream->readInt<unsigned int>();
+    for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
+    {
+        const size_t outputCount = stream->readInt<unsigned int>();
+        std::vector<GLenum> outputs(outputCount);
+        for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
+        {
+            stream->readInt(&outputs[outputIndex]);
+        }
+
+        const size_t pixelShaderSize = stream->readInt<unsigned int>();
+        const unsigned char *pixelShaderFunction = binary + stream->offset();
+        ShaderExecutable *shaderExecutable = NULL;
+        gl::Error error = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL,
+                                                    mTransformFeedbackLinkedVaryings,
+                                                    (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
+                                                    &shaderExecutable);
+        if (error.isError())
+        {
+            return gl::LinkResult(false, error);
+        }
+
+        if (!shaderExecutable)
+        {
+            infoLog.append("Could not create pixel shader.");
+            return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+        }
+
+        // add new binary
+        mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
+
+        stream->skip(pixelShaderSize);
+    }
+
+    unsigned int geometryShaderSize = stream->readInt<unsigned int>();
+
+    if (geometryShaderSize > 0)
+    {
+        const unsigned char *geometryShaderFunction = binary + stream->offset();
+        gl::Error error = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
+                                                    mTransformFeedbackLinkedVaryings,
+                                                    (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
+                                                    &mGeometryExecutable);
+        if (error.isError())
+        {
+            return gl::LinkResult(false, error);
+        }
+
+        if (!mGeometryExecutable)
+        {
+            infoLog.append("Could not create geometry shader.");
+            return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+        }
+        stream->skip(geometryShaderSize);
+    }
+
+    GUID binaryIdentifier = {0};
+    stream->readBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(GUID));
+
+    GUID identifier = mRenderer->getAdapterIdentifier();
+    if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0)
+    {
+        infoLog.append("Invalid program binary.");
+        return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+    }
+
+    initializeUniformStorage();
+
+    return gl::LinkResult(true, gl::Error(GL_NO_ERROR));
+}
+
+gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
+{
+    stream->writeInt(mShaderVersion);
+
+    stream->writeInt(mSamplersPS.size());
+    for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
+    {
+        stream->writeInt(mSamplersPS[i].active);
+        stream->writeInt(mSamplersPS[i].logicalTextureUnit);
+        stream->writeInt(mSamplersPS[i].textureType);
+    }
+
+    stream->writeInt(mSamplersVS.size());
+    for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
+    {
+        stream->writeInt(mSamplersVS[i].active);
+        stream->writeInt(mSamplersVS[i].logicalTextureUnit);
+        stream->writeInt(mSamplersVS[i].textureType);
+    }
+
+    stream->writeInt(mUsedVertexSamplerRange);
+    stream->writeInt(mUsedPixelSamplerRange);
+
+    stream->writeInt(mUniforms.size());
+    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
+    {
+        const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
+
+        stream->writeInt(uniform.type);
+        stream->writeInt(uniform.precision);
+        stream->writeString(uniform.name);
+        stream->writeInt(uniform.arraySize);
+        stream->writeInt(uniform.blockIndex);
+
+        stream->writeInt(uniform.blockInfo.offset);
+        stream->writeInt(uniform.blockInfo.arrayStride);
+        stream->writeInt(uniform.blockInfo.matrixStride);
+        stream->writeInt(uniform.blockInfo.isRowMajorMatrix);
+
+        stream->writeInt(uniform.psRegisterIndex);
+        stream->writeInt(uniform.vsRegisterIndex);
+        stream->writeInt(uniform.registerCount);
+        stream->writeInt(uniform.registerElement);
+    }
+
+    stream->writeInt(mUniformIndex.size());
+    for (size_t i = 0; i < mUniformIndex.size(); ++i)
+    {
+        stream->writeString(mUniformIndex[i].name);
+        stream->writeInt(mUniformIndex[i].element);
+        stream->writeInt(mUniformIndex[i].index);
+    }
+
+    stream->writeInt(mUniformBlocks.size());
+    for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex)
+    {
+        const gl::UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
+
+        stream->writeString(uniformBlock.name);
+        stream->writeInt(uniformBlock.elementIndex);
+        stream->writeInt(uniformBlock.dataSize);
+
+        stream->writeInt(uniformBlock.memberUniformIndexes.size());
+        for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
+        {
+            stream->writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]);
+        }
+
+        stream->writeInt(uniformBlock.psRegisterIndex);
+        stream->writeInt(uniformBlock.vsRegisterIndex);
+    }
+
+    stream->writeInt(mTransformFeedbackBufferMode);
+    stream->writeInt(mTransformFeedbackLinkedVaryings.size());
+    for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
+    {
+        const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
+
+        stream->writeString(varying.name);
+        stream->writeInt(varying.type);
+        stream->writeInt(varying.size);
+        stream->writeString(varying.semanticName);
+        stream->writeInt(varying.semanticIndex);
+        stream->writeInt(varying.semanticIndexCount);
+    }
+
+    stream->writeString(mVertexHLSL);
+    stream->writeInt(mVertexWorkarounds);
+    stream->writeString(mPixelHLSL);
+    stream->writeInt(mPixelWorkarounds);
+    stream->writeInt(mUsesFragDepth);
+    stream->writeInt(mUsesPointSize);
+
+    const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
+    stream->writeInt(pixelShaderKey.size());
+    for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++)
+    {
+        const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
+        stream->writeInt(variable.type);
+        stream->writeString(variable.name);
+        stream->writeString(variable.source);
+        stream->writeInt(variable.outputIndex);
+    }
+
+    stream->writeInt(mVertexExecutables.size());
+    for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
+    {
+        VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
+
+        for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
+        {
+            const gl::VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex];
+            stream->writeInt(vertexInput.mType);
+            stream->writeInt(vertexInput.mNormalized);
+            stream->writeInt(vertexInput.mComponents);
+            stream->writeInt(vertexInput.mPureInteger);
+        }
+
+        size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
+        stream->writeInt(vertexShaderSize);
+
+        const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
+        stream->writeBytes(vertexBlob, vertexShaderSize);
+    }
+
+    stream->writeInt(mPixelExecutables.size());
+    for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
+    {
+        PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
+
+        const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
+        stream->writeInt(outputs.size());
+        for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
+        {
+            stream->writeInt(outputs[outputIndex]);
+        }
+
+        size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
+        stream->writeInt(pixelShaderSize);
+
+        const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
+        stream->writeBytes(pixelBlob, pixelShaderSize);
+    }
+
+    size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
+    stream->writeInt(geometryShaderSize);
+
+    if (mGeometryExecutable != NULL && geometryShaderSize > 0)
+    {
+        const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
+        stream->writeBytes(geometryBlob, geometryShaderSize);
+    }
+
+    GUID binaryIdentifier = mRenderer->getAdapterIdentifier();
+    stream->writeBytes(reinterpret_cast<unsigned char*>(&binaryIdentifier), sizeof(GUID));
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExecutable)
+{
+    std::vector<GLenum> outputs;
+
+    const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender(mRenderer->getWorkarounds());
+
+    for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
+    {
+        const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
+
+        if (colorbuffer)
+        {
+            outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
+        }
+        else
+        {
+            outputs.push_back(GL_NONE);
+        }
+    }
+
+    return getPixelExecutableForOutputLayout(outputs, outExecutable);
+}
+
+gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature, ShaderExecutable **outExectuable)
+{
+    for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
+    {
+        if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
+        {
+            *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
+            return gl::Error(GL_NO_ERROR);
+        }
+    }
+
+    std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
+                                                                                     outputSignature);
+
+    // Generate new pixel executable
+    gl::InfoLog tempInfoLog;
+    ShaderExecutable *pixelExecutable = NULL;
+    gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL, SHADER_PIXEL,
+                                                     mTransformFeedbackLinkedVaryings,
+                                                     (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
+                                                     mPixelWorkarounds, &pixelExecutable);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!pixelExecutable)
+    {
+        std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
+        tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
+        ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
+    }
+    else
+    {
+        mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
+    }
+
+    *outExectuable = pixelExecutable;
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable)
+{
+    GLenum signature[gl::MAX_VERTEX_ATTRIBS];
+    getInputLayoutSignature(inputLayout, signature);
+
+    for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
+    {
+        if (mVertexExecutables[executableIndex]->matchesSignature(signature))
+        {
+            *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
+            return gl::Error(GL_NO_ERROR);
+        }
+    }
+
+    // Generate new dynamic layout with attribute conversions
+    std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes);
+
+    // Generate new vertex executable
+    gl::InfoLog tempInfoLog;
+    ShaderExecutable *vertexExecutable = NULL;
+    gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL, SHADER_VERTEX,
+                                                     mTransformFeedbackLinkedVaryings,
+                                                     (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
+                                                     mVertexWorkarounds, &vertexExecutable);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!vertexExecutable)
+    {
+        std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
+        tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
+        ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
+    }
+    else
+    {
+        mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable));
+    }
+
+    *outExectuable = vertexExecutable;
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
+                                                     int registers)
+{
+    ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
+    ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
+
+    gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS];
+    GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout);
+    ShaderExecutable *defaultVertexExecutable = NULL;
+    gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable);
+    if (error.isError())
+    {
+        return gl::LinkResult(false, error);
+    }
+
+    std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
+    ShaderExecutable *defaultPixelExecutable = NULL;
+    error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable);
+    if (error.isError())
+    {
+        return gl::LinkResult(false, error);
+    }
+
+    if (usesGeometryShader())
+    {
+        std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
+
+
+        error = mRenderer->compileToExecutable(infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
+                                               (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
+                                               ANGLE_D3D_WORKAROUND_NONE, &mGeometryExecutable);
+        if (error.isError())
+        {
+            return gl::LinkResult(false, error);
+        }
+    }
+
+#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
+    if (usesGeometryShader() && mGeometryExecutable)
+    {
+        // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level
+        // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch
+        vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
+        vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo());
+        vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
+    }
+
+    if (defaultVertexExecutable)
+    {
+        vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
+    }
+
+    if (defaultPixelExecutable)
+    {
+        fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
+    }
+#endif
+
+    bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
+    return gl::LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
+}
+
+gl::LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog,
+                                gl::Shader *fragmentShader, gl::Shader *vertexShader,
+                                const std::vector<std::string> &transformFeedbackVaryings,
+                                GLenum transformFeedbackBufferMode,
+                                int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
+                                std::map<int, gl::VariableLocation> *outputVariables)
+{
+    ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
+    ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
+
+    mSamplersPS.resize(data.caps->maxTextureImageUnits);
+    mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
+
+    mTransformFeedbackBufferMode = transformFeedbackBufferMode;
+
+    mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
+    mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
+
+    mVertexHLSL = vertexShaderD3D->getTranslatedSource();
+    mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
+    mShaderVersion = vertexShaderD3D->getShaderVersion();
+
+    // Map the varyings to the register file
+    VaryingPacking packing = { NULL };
+    *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings);
+
+    if (*registers < 0)
+    {
+        return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+    }
+
+    if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader))
+    {
+        return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+    }
+
+    if (!mDynamicHLSL->generateShaderLinkHLSL(data, infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
+                                              fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
+                                              linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
+    {
+        return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+    }
+
+    mUsesPointSize = vertexShaderD3D->usesPointSize();
+
+    return gl::LinkResult(true, gl::Error(GL_NO_ERROR));
+}
+
+void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const
+{
+    mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
+}
+
+void ProgramD3D::initializeUniformStorage()
+{
+    // Compute total default block size
+    unsigned int vertexRegisters = 0;
+    unsigned int fragmentRegisters = 0;
+    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+    {
+        const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
+
+        if (!gl::IsSampler(uniform.type))
+        {
+            if (uniform.isReferencedByVertexShader())
+            {
+                vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
+            }
+            if (uniform.isReferencedByFragmentShader())
+            {
+                fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
+            }
+        }
+    }
+
+    mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
+    mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
+}
+
+gl::Error ProgramD3D::applyUniforms()
+{
+    updateSamplerMapping();
+
+    gl::Error error = mRenderer->applyUniforms(*this, mUniforms);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+    {
+        mUniforms[uniformIndex]->dirty = false;
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error ProgramD3D::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const gl::Caps &caps)
+{
+    ASSERT(boundBuffers.size() == mUniformBlocks.size());
+
+    const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL};
+    const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL};
+
+    const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
+    const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
+
+    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++)
+    {
+        gl::UniformBlock *uniformBlock = mUniformBlocks[uniformBlockIndex];
+        gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex];
+
+        ASSERT(uniformBlock && uniformBuffer);
+
+        if (uniformBuffer->getSize() < uniformBlock->dataSize)
+        {
+            // undefined behaviour
+            return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small.");
+        }
+
+        // Unnecessary to apply an unreferenced standard or shared UBO
+        if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader())
+        {
+            continue;
+        }
+
+        if (uniformBlock->isReferencedByVertexShader())
+        {
+            unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
+            ASSERT(vertexUniformBuffers[registerIndex] == NULL);
+            ASSERT(registerIndex < caps.maxVertexUniformBlocks);
+            vertexUniformBuffers[registerIndex] = uniformBuffer;
+        }
+
+        if (uniformBlock->isReferencedByFragmentShader())
+        {
+            unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
+            ASSERT(fragmentUniformBuffers[registerIndex] == NULL);
+            ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
+            fragmentUniformBuffers[registerIndex] = uniformBuffer;
+        }
+    }
+
+    return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
+}
+
+bool ProgramD3D::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader,
+                                            unsigned int registerIndex, const gl::Caps &caps)
+{
+    if (shader == GL_VERTEX_SHADER)
+    {
+        uniformBlock->vsRegisterIndex = registerIndex;
+        if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks)
+        {
+            infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks);
+            return false;
+        }
+    }
+    else if (shader == GL_FRAGMENT_SHADER)
+    {
+        uniformBlock->psRegisterIndex = registerIndex;
+        if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks)
+        {
+            infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks);
+            return false;
+        }
+    }
+    else UNREACHABLE();
+
+    return true;
+}
+
+void ProgramD3D::dirtyAllUniforms()
+{
+    unsigned int numUniforms = mUniforms.size();
+    for (unsigned int index = 0; index < numUniforms; index++)
+    {
+        mUniforms[index]->dirty = true;
+    }
+}
+
+void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+{
+    setUniform(location, count, v, GL_FLOAT);
+}
+
+void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    setUniform(location, count, v, GL_FLOAT_VEC2);
+}
+
+void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    setUniform(location, count, v, GL_FLOAT_VEC3);
+}
+
+void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+    setUniform(location, count, v, GL_FLOAT_VEC4);
+}
+
+void ProgramD3D::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
+}
+
+void ProgramD3D::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
+}
+
+void ProgramD3D::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
+}
+
+void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
+}
+
+void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
+}
+
+void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
+}
+
+void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
+}
+
+void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
+}
+
+void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+{
+    setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
+}
+
+void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+    setUniform(location, count, v, GL_INT);
+}
+
+void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+    setUniform(location, count, v, GL_INT_VEC2);
+}
+
+void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+    setUniform(location, count, v, GL_INT_VEC3);
+}
+
+void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+    setUniform(location, count, v, GL_INT_VEC4);
+}
+
+void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    setUniform(location, count, v, GL_UNSIGNED_INT);
+}
+
+void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
+}
+
+void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
+}
+
+void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+    setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
+}
+
+void ProgramD3D::getUniformfv(GLint location, GLfloat *params)
+{
+    getUniformv(location, params, GL_FLOAT);
+}
+
+void ProgramD3D::getUniformiv(GLint location, GLint *params)
+{
+    getUniformv(location, params, GL_INT);
+}
+
+void ProgramD3D::getUniformuiv(GLint location, GLuint *params)
+{
+    getUniformv(location, params, GL_UNSIGNED_INT);
+}
+
+bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader,
+                              const gl::Caps &caps)
+{
+    const ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader.getImplementation());
+    const ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader.getImplementation());
+
+    const std::vector<sh::Uniform> &vertexUniforms = vertexShader.getUniforms();
+    const std::vector<sh::Uniform> &fragmentUniforms = fragmentShader.getUniforms();
+
+    // Check that uniforms defined in the vertex and fragment shaders are identical
+    typedef std::map<std::string, const sh::Uniform*> UniformMap;
+    UniformMap linkedUniforms;
+
+    for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++)
+    {
+        const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex];
+        linkedUniforms[vertexUniform.name] = &vertexUniform;
+    }
+
+    for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++)
+    {
+        const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex];
+        UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name);
+        if (entry != linkedUniforms.end())
+        {
+            const sh::Uniform &vertexUniform = *entry->second;
+            const std::string &uniformName = "uniform '" + vertexUniform.name + "'";
+            if (!gl::ProgramBinary::linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform))
+            {
+                return false;
+            }
+        }
+    }
+
+    for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++)
+    {
+        const sh::Uniform &uniform = vertexUniforms[uniformIndex];
+
+        if (uniform.staticUse)
+        {
+            defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name));
+        }
+    }
+
+    for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++)
+    {
+        const sh::Uniform &uniform = fragmentUniforms[uniformIndex];
+
+        if (uniform.staticUse)
+        {
+            defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name));
+        }
+    }
+
+    if (!indexUniforms(infoLog, caps))
+    {
+        return false;
+    }
+
+    initializeUniformStorage();
+
+    // special case for gl_DepthRange, the only built-in uniform (also a struct)
+    if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange())
+    {
+        const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo();
+
+        mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo));
+        mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo));
+        mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo));
+    }
+
+    return true;
+}
+
+void ProgramD3D::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister)
+{
+    ShShaderOutput outputType = ShaderD3D::getCompilerOutputType(shader);
+    sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
+    encoder.skipRegisters(uniformRegister);
+
+    defineUniform(shader, uniform, uniform.name, &encoder);
+}
+
+void ProgramD3D::defineUniform(GLenum shader, const sh::ShaderVariable &uniform,
+                                  const std::string &fullName, sh::HLSLBlockEncoder *encoder)
+{
+    if (uniform.isStruct())
+    {
+        for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
+        {
+            const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
+
+            encoder->enterAggregateType();
+
+            for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
+            {
+                const sh::ShaderVariable &field = uniform.fields[fieldIndex];
+                const std::string &fieldFullName = (fullName + elementString + "." + field.name);
+
+                defineUniform(shader, field, fieldFullName, encoder);
+            }
+
+            encoder->exitAggregateType();
+        }
+    }
+    else // Not a struct
+    {
+        // Arrays are treated as aggregate types
+        if (uniform.isArray())
+        {
+            encoder->enterAggregateType();
+        }
+
+        gl::LinkedUniform *linkedUniform = getUniformByName(fullName);
+
+        if (!linkedUniform)
+        {
+            linkedUniform = new gl::LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
+                                              -1, sh::BlockMemberInfo::getDefaultBlockInfo());
+            ASSERT(linkedUniform);
+            linkedUniform->registerElement = encoder->getCurrentElement();
+            mUniforms.push_back(linkedUniform);
+        }
+
+        ASSERT(linkedUniform->registerElement == encoder->getCurrentElement());
+
+        if (shader == GL_FRAGMENT_SHADER)
+        {
+            linkedUniform->psRegisterIndex = encoder->getCurrentRegister();
+        }
+        else if (shader == GL_VERTEX_SHADER)
+        {
+            linkedUniform->vsRegisterIndex = encoder->getCurrentRegister();
+        }
+        else UNREACHABLE();
+
+        // Advance the uniform offset, to track registers allocation for structs
+        encoder->encodeType(uniform.type, uniform.arraySize, false);
+
+        // Arrays are treated as aggregate types
+        if (uniform.isArray())
+        {
+            encoder->exitAggregateType();
+        }
+    }
+}
+
+template <typename T>
+static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
+{
+    ASSERT(dest != NULL);
+    ASSERT(dirtyFlag != NULL);
+
+    *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
+    *dest = source;
+}
+
+template <typename T>
+void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType)
+{
+    const int components = gl::VariableComponentCount(targetUniformType);
+    const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
+
+    gl::LinkedUniform *targetUniform = getUniformByLocation(location);
+
+    int elementCount = targetUniform->elementCount();
+
+    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
+
+    if (targetUniform->type == targetUniformType)
+    {
+        T *target = reinterpret_cast<T*>(targetUniform->data) + mUniformIndex[location].element * 4;
+
+        for (int i = 0; i < count; i++)
+        {
+            T *dest = target + (i * 4);
+            const T *source = v + (i * components);
+
+            for (int c = 0; c < components; c++)
+            {
+                SetIfDirty(dest + c, source[c], &targetUniform->dirty);
+            }
+            for (int c = components; c < 4; c++)
+            {
+                SetIfDirty(dest + c, T(0), &targetUniform->dirty);
+            }
+        }
+    }
+    else if (targetUniform->type == targetBoolType)
+    {
+        GLint *boolParams = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
+
+        for (int i = 0; i < count; i++)
+        {
+            GLint *dest = boolParams + (i * 4);
+            const T *source = v + (i * components);
+
+            for (int c = 0; c < components; c++)
+            {
+                SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
+            }
+            for (int c = components; c < 4; c++)
+            {
+                SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
+            }
+        }
+    }
+    else if (gl::IsSampler(targetUniform->type))
+    {
+        ASSERT(targetUniformType == GL_INT);
+
+        GLint *target = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
+
+        bool wasDirty = targetUniform->dirty;
+
+        for (int i = 0; i < count; i++)
+        {
+            GLint *dest = target + (i * 4);
+            const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components);
+
+            SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
+            SetIfDirty(dest + 1, 0, &targetUniform->dirty);
+            SetIfDirty(dest + 2, 0, &targetUniform->dirty);
+            SetIfDirty(dest + 3, 0, &targetUniform->dirty);
+        }
+
+        if (!wasDirty && targetUniform->dirty)
+        {
+            mDirtySamplerMapping = true;
+        }
+    }
+    else UNREACHABLE();
+}
+
+template<typename T>
+bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
+{
+    bool dirty = false;
+    int copyWidth = std::min(targetHeight, srcWidth);
+    int copyHeight = std::min(targetWidth, srcHeight);
+
+    for (int x = 0; x < copyWidth; x++)
+    {
+        for (int y = 0; y < copyHeight; y++)
+        {
+            SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty);
+        }
+    }
+    // clear unfilled right side
+    for (int y = 0; y < copyWidth; y++)
+    {
+        for (int x = copyHeight; x < targetWidth; x++)
+        {
+            SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+        }
+    }
+    // clear unfilled bottom.
+    for (int y = copyWidth; y < targetHeight; y++)
+    {
+        for (int x = 0; x < targetWidth; x++)
+        {
+            SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+        }
+    }
+
+    return dirty;
+}
+
+template<typename T>
+bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
+{
+    bool dirty = false;
+    int copyWidth = std::min(targetWidth, srcWidth);
+    int copyHeight = std::min(targetHeight, srcHeight);
+
+    for (int y = 0; y < copyHeight; y++)
+    {
+        for (int x = 0; x < copyWidth; x++)
+        {
+            SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty);
+        }
+    }
+    // clear unfilled right side
+    for (int y = 0; y < copyHeight; y++)
+    {
+        for (int x = copyWidth; x < targetWidth; x++)
+        {
+            SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+        }
+    }
+    // clear unfilled bottom.
+    for (int y = copyHeight; y < targetHeight; y++)
+    {
+        for (int x = 0; x < targetWidth; x++)
+        {
+            SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+        }
+    }
+
+    return dirty;
+}
+
+template <int cols, int rows>
+void ProgramD3D::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType)
+{
+    gl::LinkedUniform *targetUniform = getUniformByLocation(location);
+
+    int elementCount = targetUniform->elementCount();
+
+    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
+    const unsigned int targetMatrixStride = (4 * rows);
+    GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride);
+
+    for (int i = 0; i < count; i++)
+    {
+        // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
+        if (transpose == GL_FALSE)
+        {
+            targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty;
+        }
+        else
+        {
+            targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
+        }
+        target += targetMatrixStride;
+        value += cols * rows;
+    }
+}
+
+template <typename T>
+void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType)
+{
+    gl::LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index];
+
+    if (gl::IsMatrixType(targetUniform->type))
+    {
+        const int rows = gl::VariableRowCount(targetUniform->type);
+        const int cols = gl::VariableColumnCount(targetUniform->type);
+        transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows);
+    }
+    else if (uniformType == gl::VariableComponentType(targetUniform->type))
+    {
+        unsigned int size = gl::VariableComponentCount(targetUniform->type);
+        memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T),
+                size * sizeof(T));
+    }
+    else
+    {
+        unsigned int size = gl::VariableComponentCount(targetUniform->type);
+        switch (gl::VariableComponentType(targetUniform->type))
+        {
+          case GL_BOOL:
+            {
+                GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
+
+                for (unsigned int i = 0; i < size; i++)
+                {
+                    params[i] = (boolParams[i] == GL_FALSE) ? static_cast<T>(0) : static_cast<T>(1);
+                }
+            }
+            break;
+
+          case GL_FLOAT:
+            {
+                GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+
+                for (unsigned int i = 0; i < size; i++)
+                {
+                    params[i] = static_cast<T>(floatParams[i]);
+                }
+            }
+            break;
+
+          case GL_INT:
+            {
+                GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
+
+                for (unsigned int i = 0; i < size; i++)
+                {
+                    params[i] = static_cast<T>(intParams[i]);
+                }
+            }
+            break;
+
+          case GL_UNSIGNED_INT:
+            {
+                GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4;
+
+                for (unsigned int i = 0; i < size; i++)
+                {
+                    params[i] = static_cast<T>(uintParams[i]);
+                }
+            }
+            break;
+
+          default: UNREACHABLE();
+        }
+    }
+}
+
+template <typename VarT>
+void ProgramD3D::defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
+                                           sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
+                                           bool inRowMajorLayout)
+{
+    for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++)
+    {
+        const VarT &field = fields[uniformIndex];
+        const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
+
+        if (field.isStruct())
+        {
+            bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
+
+            for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
+            {
+                encoder->enterAggregateType();
+
+                const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
+                defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout);
+
+                encoder->exitAggregateType();
+            }
+        }
+        else
+        {
+            bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
+
+            sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
+
+            gl::LinkedUniform *newUniform = new gl::LinkedUniform(field.type, field.precision, fieldName, field.arraySize,
+                                                          blockIndex, memberInfo);
+
+            // add to uniform list, but not index, since uniform block uniforms have no location
+            blockUniformIndexes->push_back(mUniforms.size());
+            mUniforms.push_back(newUniform);
+        }
+    }
+}
+
+bool ProgramD3D::defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock,
+                                    const gl::Caps &caps)
+{
+    const ShaderD3D* shaderD3D = ShaderD3D::makeShaderD3D(shader.getImplementation());
+
+    // create uniform block entries if they do not exist
+    if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX)
+    {
+        std::vector<unsigned int> blockUniformIndexes;
+        const unsigned int blockIndex = mUniformBlocks.size();
+
+        // define member uniforms
+        sh::BlockLayoutEncoder *encoder = NULL;
+
+        if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
+        {
+            encoder = new sh::Std140BlockEncoder;
+        }
+        else
+        {
+            encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
+        }
+        ASSERT(encoder);
+
+        defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout);
+
+        size_t dataSize = encoder->getBlockSize();
+
+        // create all the uniform blocks
+        if (interfaceBlock.arraySize > 0)
+        {
+            for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++)
+            {
+                gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize);
+                newUniformBlock->memberUniformIndexes = blockUniformIndexes;
+                mUniformBlocks.push_back(newUniformBlock);
+            }
+        }
+        else
+        {
+            gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize);
+            newUniformBlock->memberUniformIndexes = blockUniformIndexes;
+            mUniformBlocks.push_back(newUniformBlock);
+        }
+    }
+
+    if (interfaceBlock.staticUse)
+    {
+        // Assign registers to the uniform blocks
+        const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name);
+        const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize);
+        ASSERT(blockIndex != GL_INVALID_INDEX);
+        ASSERT(blockIndex + elementCount <= mUniformBlocks.size());
+
+        unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name);
+
+        for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++)
+        {
+            gl::UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement];
+            ASSERT(uniformBlock->name == interfaceBlock.name);
+
+            if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(),
+                                            interfaceBlockRegister + uniformBlockElement, caps))
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+bool ProgramD3D::assignSamplers(unsigned int startSamplerIndex,
+                                   GLenum samplerType,
+                                   unsigned int samplerCount,
+                                   std::vector<Sampler> &outSamplers,
+                                   GLuint *outUsedRange)
+{
+    unsigned int samplerIndex = startSamplerIndex;
+
+    do
+    {
+        if (samplerIndex < outSamplers.size())
+        {
+            Sampler& sampler = outSamplers[samplerIndex];
+            sampler.active = true;
+            sampler.textureType = GetTextureType(samplerType);
+            sampler.logicalTextureUnit = 0;
+            *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
+        }
+        else
+        {
+            return false;
+        }
+
+        samplerIndex++;
+    } while (samplerIndex < startSamplerIndex + samplerCount);
+
+    return true;
+}
+
+bool ProgramD3D::indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps)
+{
+    ASSERT(gl::IsSampler(uniform.type));
+    ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX);
+
+    if (uniform.vsRegisterIndex != GL_INVALID_INDEX)
+    {
+        if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS,
+                            &mUsedVertexSamplerRange))
+        {
+            infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).",
+                           mSamplersVS.size());
+            return false;
+        }
+
+        unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors;
+        if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors)
+        {
+            infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)",
+                           caps.maxVertexUniformVectors);
+            return false;
+        }
+    }
+
+    if (uniform.psRegisterIndex != GL_INVALID_INDEX)
+    {
+        if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS,
+                            &mUsedPixelSamplerRange))
+        {
+            infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).",
+                           mSamplersPS.size());
+            return false;
+        }
+
+        unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors;
+        if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors)
+        {
+            infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)",
+                           caps.maxFragmentUniformVectors);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ProgramD3D::indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps)
+{
+    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+    {
+        const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
+
+        if (gl::IsSampler(uniform.type))
+        {
+            if (!indexSamplerUniform(uniform, infoLog, caps))
+            {
+                return false;
+            }
+        }
+
+        for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++)
+        {
+            mUniformIndex.push_back(gl::VariableLocation(uniform.name, arrayElementIndex, uniformIndex));
+        }
+    }
+
+    return true;
+}
+
+void ProgramD3D::reset()
+{
+    ProgramImpl::reset();
+
+    SafeDeleteContainer(mVertexExecutables);
+    SafeDeleteContainer(mPixelExecutables);
+    SafeDelete(mGeometryExecutable);
+
+    mTransformFeedbackBufferMode = GL_NONE;
+
+    mVertexHLSL.clear();
+    mVertexWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
+    mShaderVersion = 100;
+
+    mPixelHLSL.clear();
+    mPixelWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
+    mUsesFragDepth = false;
+    mPixelShaderKey.clear();
+    mUsesPointSize = false;
+
+    SafeDelete(mVertexUniformStorage);
+    SafeDelete(mFragmentUniformStorage);
+
+    mSamplersPS.clear();
+    mSamplersVS.clear();
+
+    mUsedVertexSamplerRange = 0;
+    mUsedPixelSamplerRange = 0;
+    mDirtySamplerMapping = true;
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h
index d645c57daa0..4baab9aa19c 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h
@@ -10,6 +10,7 @@
 #define LIBGLESV2_RENDERER_PROGRAMD3D_H_
 
 #include "libGLESv2/renderer/ProgramImpl.h"
+#include "libGLESv2/renderer/Workarounds.h"
 
 #include <string>
 #include <vector>
@@ -23,63 +24,194 @@ struct VertexFormat;
 
 namespace rx
 {
-
+class RendererD3D;
 class UniformStorage;
 
 class ProgramD3D : public ProgramImpl
 {
   public:
-    ProgramD3D(rx::Renderer *renderer);
+    ProgramD3D(RendererD3D *renderer);
     virtual ~ProgramD3D();
 
     static ProgramD3D *makeProgramD3D(ProgramImpl *impl);
     static const ProgramD3D *makeProgramD3D(const ProgramImpl *impl);
 
-    Renderer *getRenderer() { return mRenderer; }
-    DynamicHLSL *getDynamicHLSL() { return mDynamicHLSL; }
-    const std::vector<rx::PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; }
-
-    GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; }
-    bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
-    bool save(gl::BinaryOutputStream *stream);
+    const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; }
+    int getShaderVersion() const { return mShaderVersion; }
+    GLenum getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
 
-    ShaderExecutable *getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector<GLenum> &outputSignature,
-                                                        const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
-                                                        bool separatedOutputBuffers);
-    ShaderExecutable *getVertexExecutableForInputLayout(gl::InfoLog &infoLog,
-                                                        const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
-                                                        const sh::Attribute shaderAttributes[],
-                                                        const std::vector<gl::LinkedVarying> &transformFeedbackLinkedVaryings,
-                                                        bool separatedOutputBuffers);
+    GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const;
+    GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const;
+    GLint getUsedSamplerRange(gl::SamplerType type) const;
+    void updateSamplerMapping();
+    bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps);
 
-    bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
-              const std::vector<std::string> &transformFeedbackVaryings, int *registers,
-              std::vector<gl::LinkedVarying> *linkedVaryings, std::map<int, gl::VariableLocation> *outputVariables);
+    bool usesPointSize() const { return mUsesPointSize; }
+    bool usesPointSpriteEmulation() const;
+    bool usesGeometryShader() const;
 
-    // D3D only
-    void initializeUniformStorage(const std::vector<gl::LinkedUniform*> &uniforms);
+    GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; }
+    gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
+    gl::Error save(gl::BinaryOutputStream *stream);
+
+    gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExectuable);
+    gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout, ShaderExecutable **outExectuable);
+    gl::Error getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable);
+    ShaderExecutable *getGeometryExecutable() const { return mGeometryExecutable; }
+
+    gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
+                                             int registers);
+
+    gl::LinkResult link(const gl::Data &data, gl::InfoLog &infoLog,
+                        gl::Shader *fragmentShader, gl::Shader *vertexShader,
+                        const std::vector<std::string> &transformFeedbackVaryings,
+                        GLenum transformFeedbackBufferMode,
+                        int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
+                        std::map<int, gl::VariableLocation> *outputVariables);
+
+    void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const;
+
+    void initializeUniformStorage();
+    gl::Error applyUniforms();
+    gl::Error applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const gl::Caps &caps);
+    bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader,
+                                    unsigned int registerIndex, const gl::Caps &caps);
+    void dirtyAllUniforms();
+
+    void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
+    void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
+    void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
+    void setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
+    void setUniform1iv(GLint location, GLsizei count, const GLint *v);
+    void setUniform2iv(GLint location, GLsizei count, const GLint *v);
+    void setUniform3iv(GLint location, GLsizei count, const GLint *v);
+    void setUniform4iv(GLint location, GLsizei count, const GLint *v);
+    void setUniform1uiv(GLint location, GLsizei count, const GLuint *v);
+    void setUniform2uiv(GLint location, GLsizei count, const GLuint *v);
+    void setUniform3uiv(GLint location, GLsizei count, const GLuint *v);
+    void setUniform4uiv(GLint location, GLsizei count, const GLuint *v);
+    void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+    void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+
+    void getUniformfv(GLint location, GLfloat *params);
+    void getUniformiv(GLint location, GLint *params);
+    void getUniformuiv(GLint location, GLuint *params);
 
     const UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; }
     const UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
 
+    bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader,
+                      const gl::Caps &caps);
+    bool defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, const gl::Caps &caps);
+
     void reset();
 
   private:
     DISALLOW_COPY_AND_ASSIGN(ProgramD3D);
 
-    Renderer *mRenderer;
+    class VertexExecutable
+    {
+      public:
+        VertexExecutable(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
+                         const GLenum signature[gl::MAX_VERTEX_ATTRIBS],
+                         ShaderExecutable *shaderExecutable);
+        ~VertexExecutable();
+
+        bool matchesSignature(const GLenum convertedLayout[gl::MAX_VERTEX_ATTRIBS]) const;
+
+        const gl::VertexFormat *inputs() const { return mInputs; }
+        const GLenum *signature() const { return mSignature; }
+        ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
+
+      private:
+        gl::VertexFormat mInputs[gl::MAX_VERTEX_ATTRIBS];
+        GLenum mSignature[gl::MAX_VERTEX_ATTRIBS];
+        ShaderExecutable *mShaderExecutable;
+    };
+
+    class PixelExecutable
+    {
+      public:
+        PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutable *shaderExecutable);
+        ~PixelExecutable();
+
+        bool matchesSignature(const std::vector<GLenum> &signature) const { return mOutputSignature == signature; }
+
+        const std::vector<GLenum> &outputSignature() const { return mOutputSignature; }
+        ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
+
+      private:
+        std::vector<GLenum> mOutputSignature;
+        ShaderExecutable *mShaderExecutable;
+    };
+
+    struct Sampler
+    {
+        Sampler();
+
+        bool active;
+        GLint logicalTextureUnit;
+        GLenum textureType;
+    };
+
+    void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister);
+    void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName,
+                       sh::HLSLBlockEncoder *encoder);
+    bool indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps);
+    bool indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps);
+    static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount,
+                               std::vector<Sampler> &outSamplers, GLuint *outUsedRange);
+
+    template <typename T>
+    void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType);
+
+    template <int cols, int rows>
+    void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType);
+
+    template <typename T>
+    void getUniformv(GLint location, T *params, GLenum uniformType);
+
+    template <typename VarT>
+    void defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
+                                   sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
+                                   bool inRowMajorLayout);
+
+    RendererD3D *mRenderer;
     DynamicHLSL *mDynamicHLSL;
 
+    std::vector<VertexExecutable *> mVertexExecutables;
+    std::vector<PixelExecutable *> mPixelExecutables;
+    ShaderExecutable *mGeometryExecutable;
+
     std::string mVertexHLSL;
-    rx::D3DWorkaroundType mVertexWorkarounds;
+    D3DWorkaroundType mVertexWorkarounds;
 
     std::string mPixelHLSL;
-    rx::D3DWorkaroundType mPixelWorkarounds;
+    D3DWorkaroundType mPixelWorkarounds;
     bool mUsesFragDepth;
-    std::vector<rx::PixelShaderOutputVariable> mPixelShaderKey;
+    std::vector<PixelShaderOutputVariable> mPixelShaderKey;
+
+    bool mUsesPointSize;
 
     UniformStorage *mVertexUniformStorage;
     UniformStorage *mFragmentUniformStorage;
+
+    GLenum mTransformFeedbackBufferMode;
+
+    std::vector<Sampler> mSamplersPS;
+    std::vector<Sampler> mSamplersVS;
+    GLuint mUsedVertexSamplerRange;
+    GLuint mUsedPixelSamplerRange;
+    bool mDirtySamplerMapping;
+
+    int mShaderVersion;
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp
new file mode 100644
index 00000000000..cb4af367a2b
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp
@@ -0,0 +1,108 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferD3d.cpp: Implements the RenderbufferD3D class, a specialization of RenderbufferImpl
+
+
+#include "libGLESv2/renderer/d3d/RenderbufferD3D.h"
+
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
+#include "libGLESv2/renderer/RenderTarget.h"
+
+namespace rx
+{
+RenderbufferD3D::RenderbufferD3D(RendererD3D *renderer) : mRenderer(renderer)
+{
+    mRenderTarget = NULL;
+}
+
+RenderbufferD3D::~RenderbufferD3D()
+{
+    SafeDelete(mRenderTarget);
+}
+
+RenderbufferD3D *RenderbufferD3D::makeRenderbufferD3D(RenderbufferImpl *renderbuffer)
+{
+    ASSERT(HAS_DYNAMIC_TYPE(RenderbufferD3D*, renderbuffer));
+    return static_cast<RenderbufferD3D*>(renderbuffer);
+}
+
+gl::Error RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
+{
+    // If the renderbuffer parameters are queried, the calling function
+    // will expect one of the valid renderbuffer formats for use in
+    // glRenderbufferStorage, but we should create depth and stencil buffers
+    // as DEPTH24_STENCIL8
+    GLenum creationFormat = internalformat;
+    if (internalformat == GL_DEPTH_COMPONENT16 || internalformat == GL_STENCIL_INDEX8)
+    {
+        creationFormat = GL_DEPTH24_STENCIL8_OES;
+    }
+
+    RenderTarget *newRT = NULL;
+    gl::Error error = mRenderer->createRenderTarget(width, height, creationFormat, samples, &newRT);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    SafeDelete(mRenderTarget);
+    mRenderTarget = newRT;
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RenderbufferD3D::setStorage(SwapChain *swapChain, bool depth)
+{
+    RenderTarget *newRT = NULL;
+    gl::Error error = mRenderer->createRenderTarget(swapChain, depth, &newRT);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    SafeDelete(mRenderTarget);
+    mRenderTarget = newRT;
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+GLsizei RenderbufferD3D::getWidth() const
+{
+    return (mRenderTarget ? mRenderTarget->getWidth() : 0);
+}
+
+GLsizei RenderbufferD3D::getHeight() const
+{
+    return (mRenderTarget ? mRenderTarget->getHeight() : 0);
+}
+
+GLenum RenderbufferD3D::getInternalFormat() const
+{
+    return (mRenderTarget ? mRenderTarget->getInternalFormat() : GL_RGBA4);
+}
+
+GLenum RenderbufferD3D::getActualFormat() const
+{
+    return (mRenderTarget ? mRenderTarget->getActualFormat() : GL_RGBA4);
+}
+
+GLsizei RenderbufferD3D::getSamples() const
+{
+    return (mRenderTarget ? mRenderTarget->getSamples() : 0);
+}
+
+RenderTarget *RenderbufferD3D::getRenderTarget()
+{
+    return mRenderTarget;
+}
+
+unsigned int RenderbufferD3D::getRenderTargetSerial() const
+{
+    return (mRenderTarget ? mRenderTarget->getSerial() : 0);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h
new file mode 100644
index 00000000000..9440a449f2c
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h
@@ -0,0 +1,51 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferD3d.h: Defines the RenderbufferD3D class which implements RenderbufferImpl.
+
+#ifndef LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_
+#define LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_
+
+#include "angle_gl.h"
+
+#include "common/angleutils.h"
+#include "libGLESv2/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+class RendererD3D;
+class RenderTarget;
+class SwapChain;
+
+class RenderbufferD3D : public RenderbufferImpl
+{
+  public:
+    RenderbufferD3D(RendererD3D *renderer);
+    virtual ~RenderbufferD3D();
+
+    static RenderbufferD3D *makeRenderbufferD3D(RenderbufferImpl *renderbuffer);
+
+    virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) override;
+    gl::Error setStorage(SwapChain *swapChain, bool depth);
+
+    virtual GLsizei getWidth() const;
+    virtual GLsizei getHeight() const;
+    virtual GLenum getInternalFormat() const;
+    virtual GLenum getActualFormat() const;
+    virtual GLsizei getSamples() const;
+
+    RenderTarget *getRenderTarget();
+    unsigned int getRenderTargetSerial() const;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(RenderbufferD3D);
+
+    RendererD3D *mRenderer;
+    RenderTarget *mRenderTarget;
+};
+}
+
+#endif // LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
new file mode 100644
index 00000000000..97da6da7fdc
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
@@ -0,0 +1,796 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RendererD3D.cpp: Implementation of the base D3D Renderer.
+
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
+
+#include "libGLESv2/renderer/d3d/IndexDataManager.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
+#include "libGLESv2/ResourceManager.h"
+#include "libGLESv2/State.h"
+#include "libGLESv2/VertexArray.h"
+#include "libGLESv2/formatutils.h"
+#include "common/utilities.h"
+
+namespace rx
+{
+
+RendererD3D::RendererD3D(egl::Display *display)
+    : mDisplay(display)
+{
+}
+
+RendererD3D::~RendererD3D()
+{
+    for (gl::TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); ++i)
+    {
+        i->second.set(NULL);
+    }
+    mIncompleteTextures.clear();
+}
+
+// static
+RendererD3D *RendererD3D::makeRendererD3D(Renderer *renderer)
+{
+    ASSERT(HAS_DYNAMIC_TYPE(RendererD3D*, renderer));
+    return static_cast<RendererD3D*>(renderer);
+}
+
+gl::Error RendererD3D::drawElements(const gl::Data &data,
+                                    GLenum mode, GLsizei count, GLenum type,
+                                    const GLvoid *indices, GLsizei instances,
+                                    const RangeUI &indexRange)
+{
+    ASSERT(data.state->getCurrentProgramId() != 0);
+
+    gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary();
+    programBinary->updateSamplerMapping();
+
+    gl::Error error = generateSwizzles(data);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!applyPrimitiveType(mode, count))
+    {
+        return gl::Error(GL_NO_ERROR);
+    }
+
+    error = applyRenderTarget(data, mode, false);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = applyState(data, mode);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    gl::VertexArray *vao = data.state->getVertexArray();
+    TranslatedIndexData indexInfo;
+    indexInfo.indexRange = indexRange;
+    error = applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    GLsizei vertexCount = indexInfo.indexRange.length() + 1;
+    error = applyVertexBuffer(*data.state, indexInfo.indexRange.start, vertexCount, instances);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    bool transformFeedbackActive = applyTransformFeedbackBuffers(data);
+    // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation
+    // layer.
+    ASSERT(!transformFeedbackActive);
+
+    error = applyShaders(data, transformFeedbackActive);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = applyTextures(data);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = applyUniformBuffers(data);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!skipDraw(data, mode))
+    {
+        error = drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RendererD3D::drawArrays(const gl::Data &data,
+                                  GLenum mode, GLint first,
+                                  GLsizei count, GLsizei instances)
+{
+    ASSERT(data.state->getCurrentProgramId() != 0);
+
+    gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary();
+    programBinary->updateSamplerMapping();
+
+    gl::Error error = generateSwizzles(data);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!applyPrimitiveType(mode, count))
+    {
+        return gl::Error(GL_NO_ERROR);
+    }
+
+    error = applyRenderTarget(data, mode, false);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = applyState(data, mode);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = applyVertexBuffer(*data.state, first, count, instances);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    bool transformFeedbackActive = applyTransformFeedbackBuffers(data);
+
+    error = applyShaders(data, transformFeedbackActive);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = applyTextures(data);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = applyUniformBuffers(data);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!skipDraw(data, mode))
+    {
+        error = drawArrays(mode, count, instances, transformFeedbackActive);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        if (transformFeedbackActive)
+        {
+            markTransformFeedbackUsage(data);
+        }
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RendererD3D::generateSwizzles(const gl::Data &data, gl::SamplerType type)
+{
+    gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary();
+
+    size_t samplerRange = programBinary->getUsedSamplerRange(type);
+
+    for (size_t i = 0; i < samplerRange; i++)
+    {
+        GLenum textureType = programBinary->getSamplerTextureType(type, i);
+        GLint textureUnit = programBinary->getSamplerMapping(type, i, *data.caps);
+        if (textureUnit != -1)
+        {
+            gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType);
+            ASSERT(texture);
+            if (texture->getSamplerState().swizzleRequired())
+            {
+                gl::Error error = generateSwizzle(texture);
+                if (error.isError())
+                {
+                    return error;
+                }
+            }
+        }
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RendererD3D::generateSwizzles(const gl::Data &data)
+{
+    gl::Error error = generateSwizzles(data, gl::SAMPLER_VERTEX);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = generateSwizzles(data, gl::SAMPLER_PIXEL);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+// Applies the render target surface, depth stencil surface, viewport rectangle and
+// scissor rectangle to the renderer
+gl::Error RendererD3D::applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport)
+{
+    const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
+    ASSERT(framebufferObject && framebufferObject->completeness(data) == GL_FRAMEBUFFER_COMPLETE);
+
+    gl::Error error = applyRenderTarget(framebufferObject);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    float nearZ, farZ;
+    data.state->getDepthRange(&nearZ, &farZ);
+    setViewport(data.state->getViewport(), nearZ, farZ, drawMode,
+                data.state->getRasterizerState().frontFace, ignoreViewport);
+
+    setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D device
+gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode)
+{
+    const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
+    int samples = framebufferObject->getSamples(data);
+
+    gl::RasterizerState rasterizer = data.state->getRasterizerState();
+    rasterizer.pointDrawMode = (drawMode == GL_POINTS);
+    rasterizer.multiSample = (samples != 0);
+
+    gl::Error error = setRasterizerState(rasterizer);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    unsigned int mask = 0;
+    if (data.state->isSampleCoverageEnabled())
+    {
+        GLclampf coverageValue;
+        bool coverageInvert = false;
+        data.state->getSampleCoverageParams(&coverageValue, &coverageInvert);
+        if (coverageValue != 0)
+        {
+            float threshold = 0.5f;
+
+            for (int i = 0; i < samples; ++i)
+            {
+                mask <<= 1;
+
+                if ((i + 1) * coverageValue >= threshold)
+                {
+                    threshold += 1.0f;
+                    mask |= 1;
+                }
+            }
+        }
+
+        if (coverageInvert)
+        {
+            mask = ~mask;
+        }
+    }
+    else
+    {
+        mask = 0xFFFFFFFF;
+    }
+    error = setBlendState(framebufferObject, data.state->getBlendState(), data.state->getBlendColor(), mask);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = setDepthStencilState(data.state->getDepthStencilState(), data.state->getStencilRef(),
+                                 data.state->getStencilBackRef(), rasterizer.frontFace == GL_CCW);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+bool RendererD3D::applyTransformFeedbackBuffers(const gl::Data &data)
+{
+    gl::TransformFeedback *curTransformFeedback = data.state->getCurrentTransformFeedback();
+    if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
+    {
+        applyTransformFeedbackBuffers(*data.state);
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+// Applies the shaders and shader constants to the Direct3D device
+gl::Error RendererD3D::applyShaders(const gl::Data &data, bool transformFeedbackActive)
+{
+    gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary();
+
+    gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS];
+    gl::VertexFormat::GetInputLayout(inputLayout, programBinary, *data.state);
+
+    const gl::Framebuffer *fbo = data.state->getDrawFramebuffer();
+
+    gl::Error error = applyShaders(programBinary, inputLayout, fbo, data.state->getRasterizerState().rasterizerDiscard, transformFeedbackActive);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return programBinary->applyUniforms();
+}
+
+// For each Direct3D sampler of either the pixel or vertex stage,
+// looks up the corresponding OpenGL texture image unit and texture type,
+// and sets the texture and its addressing/filtering state (or NULL when inactive).
+gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shaderType,
+                                     const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount)
+{
+    gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary();
+
+    size_t samplerRange = programBinary->getUsedSamplerRange(shaderType);
+    for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
+    {
+        GLenum textureType = programBinary->getSamplerTextureType(shaderType, samplerIndex);
+        GLint textureUnit = programBinary->getSamplerMapping(shaderType, samplerIndex, *data.caps);
+        if (textureUnit != -1)
+        {
+            gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType);
+            ASSERT(texture);
+            gl::SamplerState sampler = texture->getSamplerState();
+
+            gl::Sampler *samplerObject = data.state->getSampler(textureUnit);
+            if (samplerObject)
+            {
+                samplerObject->getState(&sampler);
+            }
+
+            // TODO: std::binary_search may become unavailable using older versions of GCC
+            if (texture->isSamplerComplete(sampler, *data.textureCaps, *data.extensions, data.clientVersion) &&
+                !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial()))
+            {
+                gl::Error error = setSamplerState(shaderType, samplerIndex, texture, sampler);
+                if (error.isError())
+                {
+                    return error;
+                }
+
+                error = setTexture(shaderType, samplerIndex, texture);
+                if (error.isError())
+                {
+                    return error;
+                }
+            }
+            else
+            {
+                // Texture is not sampler complete or it is in use by the framebuffer.  Bind the incomplete texture.
+                gl::Texture *incompleteTexture = getIncompleteTexture(textureType);
+                gl::Error error = setTexture(shaderType, samplerIndex, incompleteTexture);
+                if (error.isError())
+                {
+                    return error;
+                }
+            }
+        }
+        else
+        {
+            // No texture bound to this slot even though it is used by the shader, bind a NULL texture
+            gl::Error error = setTexture(shaderType, samplerIndex, NULL);
+            if (error.isError())
+            {
+                return error;
+            }
+        }
+    }
+
+    // Set all the remaining textures to NULL
+    size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? data.caps->maxTextureImageUnits
+                                                            : data.caps->maxVertexTextureImageUnits;
+    for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
+    {
+        gl::Error error = setTexture(shaderType, samplerIndex, NULL);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RendererD3D::applyTextures(const gl::Data &data)
+{
+    FramebufferTextureSerialArray framebufferSerials;
+    size_t framebufferSerialCount = getBoundFramebufferTextureSerials(data, &framebufferSerials);
+
+    gl::Error error = applyTextures(data, gl::SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = applyTextures(data, gl::SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RendererD3D::applyUniformBuffers(const gl::Data &data)
+{
+    gl::Program *programObject = data.resourceManager->getProgram(data.state->getCurrentProgramId());
+    gl::ProgramBinary *programBinary = programObject->getProgramBinary();
+
+    std::vector<gl::Buffer*> boundBuffers;
+
+    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++)
+    {
+        GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex);
+
+        if (data.state->getIndexedUniformBuffer(blockBinding)->id() == 0)
+        {
+            // undefined behaviour
+            return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer.");
+        }
+        else
+        {
+            gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(blockBinding);
+            ASSERT(uniformBuffer);
+            boundBuffers.push_back(uniformBuffer);
+        }
+    }
+
+    return programBinary->applyUniformBuffers(boundBuffers, *data.caps);
+}
+
+bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode)
+{
+    if (drawMode == GL_POINTS)
+    {
+        // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
+        // which affects varying interpolation. Since the value of gl_PointSize is
+        // undefined when not written, just skip drawing to avoid unexpected results.
+        if (!data.state->getCurrentProgramBinary()->usesPointSize())
+        {
+            // This is stictly speaking not an error, but developers should be
+            // notified of risking undefined behavior.
+            ERR("Point rendering without writing to gl_PointSize.");
+
+            return true;
+        }
+    }
+    else if (gl::IsTriangleMode(drawMode))
+    {
+        if (data.state->getRasterizerState().cullFace && data.state->getRasterizerState().cullMode == GL_FRONT_AND_BACK)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void RendererD3D::markTransformFeedbackUsage(const gl::Data &data)
+{
+    for (size_t i = 0; i < data.caps->maxTransformFeedbackSeparateAttributes; i++)
+    {
+        gl::Buffer *buffer = data.state->getIndexedTransformFeedbackBuffer(i);
+        if (buffer)
+        {
+            buffer->markTransformFeedbackUsage();
+        }
+    }
+}
+
+size_t RendererD3D::getBoundFramebufferTextureSerials(const gl::Data &data,
+                                                      FramebufferTextureSerialArray *outSerialArray)
+{
+    size_t serialCount = 0;
+
+    const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer();
+    for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
+    {
+        gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i);
+        if (attachment && attachment->isTexture())
+        {
+            gl::Texture *texture = attachment->getTexture();
+            (*outSerialArray)[serialCount++] = texture->getTextureSerial();
+        }
+    }
+
+    gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer();
+    if (depthStencilAttachment && depthStencilAttachment->isTexture())
+    {
+        gl::Texture *depthStencilTexture = depthStencilAttachment->getTexture();
+        (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial();
+    }
+
+    std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount);
+
+    return serialCount;
+}
+
+gl::Texture *RendererD3D::getIncompleteTexture(GLenum type)
+{
+    if (mIncompleteTextures.find(type) == mIncompleteTextures.end())
+    {
+        const GLubyte color[] = { 0, 0, 0, 255 };
+        const gl::PixelUnpackState incompleteUnpackState(1);
+
+        gl::Texture* t = NULL;
+        switch (type)
+        {
+          default:
+            UNREACHABLE();
+            // default falls through to TEXTURE_2D
+
+          case GL_TEXTURE_2D:
+            {
+                gl::Texture2D *incomplete2d = new gl::Texture2D(createTexture(GL_TEXTURE_2D), gl::Texture::INCOMPLETE_TEXTURE_ID);
+                incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+                t = incomplete2d;
+            }
+            break;
+
+          case GL_TEXTURE_CUBE_MAP:
+            {
+              gl::TextureCubeMap *incompleteCube = new gl::TextureCubeMap(createTexture(GL_TEXTURE_CUBE_MAP), gl::Texture::INCOMPLETE_TEXTURE_ID);
+
+              incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+              incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+              incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+              incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+              incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+              incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+
+              t = incompleteCube;
+            }
+            break;
+
+          case GL_TEXTURE_3D:
+            {
+                gl::Texture3D *incomplete3d = new gl::Texture3D(createTexture(GL_TEXTURE_3D), gl::Texture::INCOMPLETE_TEXTURE_ID);
+                incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+
+                t = incomplete3d;
+            }
+            break;
+
+          case GL_TEXTURE_2D_ARRAY:
+            {
+                gl::Texture2DArray *incomplete2darray = new gl::Texture2DArray(createTexture(GL_TEXTURE_2D_ARRAY), gl::Texture::INCOMPLETE_TEXTURE_ID);
+                incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+
+                t = incomplete2darray;
+            }
+            break;
+        }
+
+        mIncompleteTextures[type].set(t);
+    }
+
+    return mIncompleteTextures[type].get();
+}
+
+gl::Error RendererD3D::clear(const gl::Data &data, GLbitfield mask)
+{
+    gl::ClearParameters clearParams = data.state->getClearParameters(mask);
+
+    // Clips the clear to the scissor rectangle but not the viewport
+    gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return clear(clearParams, data.state->getDrawFramebuffer());
+}
+
+gl::Error RendererD3D::clearBufferfv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLfloat *values)
+{
+    // glClearBufferfv can be called to clear the color buffer or depth buffer
+    gl::ClearParameters clearParams = data.state->getClearParameters(0);
+
+    if (buffer == GL_COLOR)
+    {
+        for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+        {
+            clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+        }
+        clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
+        clearParams.colorClearType = GL_FLOAT;
+    }
+
+    if (buffer == GL_DEPTH)
+    {
+        clearParams.clearDepth = true;
+        clearParams.depthClearValue = values[0];
+    }
+
+    // Clips the clear to the scissor rectangle but not the viewport
+    gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return clear(clearParams, data.state->getDrawFramebuffer());
+}
+
+gl::Error RendererD3D::clearBufferuiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLuint *values)
+{
+    // glClearBufferuiv can only be called to clear a color buffer
+    gl::ClearParameters clearParams = data.state->getClearParameters(0);
+    for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+    {
+        clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+    }
+    clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
+    clearParams.colorClearType = GL_UNSIGNED_INT;
+
+    // Clips the clear to the scissor rectangle but not the viewport
+    gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return clear(clearParams, data.state->getDrawFramebuffer());
+}
+
+gl::Error RendererD3D::clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values)
+{
+    // glClearBufferiv can be called to clear the color buffer or stencil buffer
+    gl::ClearParameters clearParams = data.state->getClearParameters(0);
+
+    if (buffer == GL_COLOR)
+    {
+        for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+        {
+            clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+        }
+        clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
+        clearParams.colorClearType = GL_INT;
+    }
+
+    if (buffer == GL_STENCIL)
+    {
+        clearParams.clearStencil = true;
+        clearParams.stencilClearValue = values[1];
+    }
+
+    // Clips the clear to the scissor rectangle but not the viewport
+    gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return clear(clearParams, data.state->getDrawFramebuffer());
+}
+
+gl::Error RendererD3D::clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer,
+                                     GLfloat depth, GLint stencil)
+{
+    if (data.state->isRasterizerDiscardEnabled())
+    {
+        return gl::Error(GL_NO_ERROR);
+    }
+
+    // glClearBufferfi can only be called to clear a depth stencil buffer
+    gl::ClearParameters clearParams = data.state->getClearParameters(0);
+    clearParams.clearDepth = true;
+    clearParams.depthClearValue = depth;
+    clearParams.clearStencil = true;
+    clearParams.stencilClearValue = stencil;
+
+    // Clips the clear to the scissor rectangle but not the viewport
+    gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return clear(clearParams, data.state->getDrawFramebuffer());
+}
+
+gl::Error RendererD3D::blitFramebuffer(const gl::Data &data,
+                                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                                       GLbitfield mask, GLenum filter)
+{
+    const gl::Framebuffer *readFramebuffer = data.state->getReadFramebuffer();
+    const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer();
+
+    bool blitRenderTarget = false;
+    bool blitDepth = false;
+    bool blitStencil = false;
+    if ((mask & GL_COLOR_BUFFER_BIT) && readFramebuffer->getReadColorbuffer() && drawFramebuffer->getFirstColorbuffer())
+    {
+        blitRenderTarget = true;
+    }
+    if ((mask & GL_STENCIL_BUFFER_BIT) && readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
+    {
+        blitStencil = true;
+    }
+    if ((mask & GL_DEPTH_BUFFER_BIT) && readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
+    {
+        blitDepth = true;
+    }
+
+    gl::Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
+    gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
+    if (blitRenderTarget || blitDepth || blitStencil)
+    {
+        const gl::Rectangle *scissor = data.state->isScissorTestEnabled() ? &data.state->getScissor() : NULL;
+        gl::Error error = blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor,
+                                   blitRenderTarget, blitDepth, blitStencil, filter);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RendererD3D::readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height,
+                                  GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
+{
+    const gl::Framebuffer *framebuffer = data.state->getReadFramebuffer();
+
+    GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
+    const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
+    GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, data.state->getPackAlignment());
+
+    return readPixels(framebuffer, x, y, width, height, format, type, outputPitch, data.state->getPackState(),
+                      reinterpret_cast<uint8_t*>(pixels));
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h
new file mode 100644
index 00000000000..99192076677
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h
@@ -0,0 +1,195 @@
+
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RendererD3D.h: Defines a back-end specific class for the DirectX renderer.
+
+#ifndef LIBGLESV2_RENDERER_RENDERERD3D_H_
+#define LIBGLESV2_RENDERER_RENDERERD3D_H_
+
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/Data.h"
+
+//FIXME(jmadill): std::array is currently prohibited by Chromium style guide
+#include <array>
+
+namespace gl
+{
+class InfoLog;
+struct LinkedVarying;
+class Texture;
+}
+
+namespace rx
+{
+class TextureStorage;
+class VertexBuffer;
+class IndexBuffer;
+class ShaderExecutable;
+class SwapChain;
+class RenderTarget;
+class Image;
+class TextureStorage;
+class UniformStorage;
+
+class RendererD3D : public Renderer
+{
+  public:
+    explicit RendererD3D(egl::Display *display);
+    virtual ~RendererD3D();
+
+    static RendererD3D *makeRendererD3D(Renderer *renderer);
+
+    gl::Error drawArrays(const gl::Data &data,
+                         GLenum mode, GLint first,
+                         GLsizei count, GLsizei instances) override;
+
+    gl::Error drawElements(const gl::Data &data,
+                           GLenum mode, GLsizei count, GLenum type,
+                           const GLvoid *indices, GLsizei instances,
+                           const RangeUI &indexRange) override;
+
+    gl::Error clear(const gl::Data &data, GLbitfield mask) override;
+    gl::Error clearBufferfv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLfloat *values) override;
+    gl::Error clearBufferuiv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLuint *values) override;
+    gl::Error clearBufferiv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLint *values) override;
+    gl::Error clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override;
+
+    gl::Error readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height,
+                         GLenum format, GLenum type, GLsizei *bufSize, void* pixels) override;
+
+    gl::Error blitFramebuffer(const gl::Data &data,
+                              GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+                              GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                              GLbitfield mask, GLenum filter) override;
+
+    // Direct3D Specific methods
+    virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
+
+    virtual gl::Error generateSwizzle(gl::Texture *texture) = 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 setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) = 0;
+
+    virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0;
+    virtual gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
+                                    unsigned int sampleMask) = 0;
+    virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
+                                           int stencilBackRef, bool frontFaceCCW) = 0;
+
+    virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0;
+    virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
+                             bool ignoreViewport) = 0;
+
+    virtual gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) = 0;
+    virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
+                                   bool rasterizerDiscard, bool transformFeedbackActive) = 0;
+    virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray) = 0;
+    virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
+    virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) = 0;
+    virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0;
+    virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0;
+
+    virtual void markAllStateDirty() = 0;
+
+    virtual unsigned int getReservedVertexUniformVectors() const = 0;
+    virtual unsigned int getReservedFragmentUniformVectors() const = 0;
+    virtual unsigned int getReservedVertexUniformBuffers() const = 0;
+    virtual unsigned int getReservedFragmentUniformBuffers() const = 0;
+    virtual bool getShareHandleSupport() const = 0;
+    virtual bool getPostSubBufferSupport() const = 0;
+
+    // Pixel operations
+    virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                  GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) = 0;
+    virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                    GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) = 0;
+    virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                  GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0;
+    virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                       GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0;
+
+    virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+                                 GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) = 0;
+
+    // RenderTarget creation
+    virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) = 0;
+    virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) = 0;
+
+    // Shader operations
+    virtual void releaseShaderCompiler() = 0;
+    virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type,
+                                     const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+                                     bool separatedOutputBuffers, ShaderExecutable **outExecutable) = 0;
+    virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
+                                          const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+                                          bool separatedOutputBuffers, D3DWorkaroundType workaround,
+                                          ShaderExecutable **outExectuable) = 0;
+    virtual UniformStorage *createUniformStorage(size_t storageSize) = 0;
+
+    // Image operations
+    virtual Image *createImage() = 0;
+    virtual gl::Error generateMipmap(Image *dest, Image *source) = 0;
+    virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0;
+    virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) = 0;
+    virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) = 0;
+    virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
+    virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
+
+    // Buffer-to-texture and Texture-to-buffer copies
+    virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0;
+    virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+                                              GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0;
+
+    virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0;
+    virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0;
+
+    virtual VertexBuffer *createVertexBuffer() = 0;
+    virtual IndexBuffer *createIndexBuffer() = 0;
+
+  protected:
+    virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0;
+    virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
+                                   gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0;
+    virtual gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) = 0;
+    virtual gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect,
+                               const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
+                               const gl::Rectangle *scissor, bool blitRenderTarget,
+                               bool blitDepth, bool blitStencil, GLenum filter) = 0;
+
+    egl::Display *mDisplay;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(RendererD3D);
+
+    //FIXME(jmadill): std::array is currently prohibited by Chromium style guide
+    typedef std::array<unsigned int, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureSerialArray;
+
+    gl::Error generateSwizzles(const gl::Data &data, gl::SamplerType type);
+    gl::Error generateSwizzles(const gl::Data &data);
+
+    gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport);
+    gl::Error applyState(const gl::Data &data, GLenum drawMode);
+    bool applyTransformFeedbackBuffers(const gl::Data &data);
+    gl::Error applyShaders(const gl::Data &data, bool transformFeedbackActive);
+    gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType,
+                            const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount);
+    gl::Error applyTextures(const gl::Data &data);
+    gl::Error applyUniformBuffers(const gl::Data &data);
+
+    bool skipDraw(const gl::Data &data, GLenum drawMode);
+    void markTransformFeedbackUsage(const gl::Data &data);
+
+    size_t getBoundFramebufferTextureSerials(const gl::Data &data,
+                                             FramebufferTextureSerialArray *outSerialArray);
+    gl::Texture *getIncompleteTexture(GLenum type);
+
+    gl::TextureMap mIncompleteTextures;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_RENDERERD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp
index c472113ebac..8a97579e16a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp
@@ -6,13 +6,36 @@
 
 // ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl.
 
-#include "libGLESv2/renderer/d3d/ShaderD3D.h"
-#include "libGLESv2/renderer/Renderer.h"
 #include "libGLESv2/Shader.h"
 #include "libGLESv2/main.h"
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
+#include "libGLESv2/renderer/d3d/ShaderD3D.h"
 
+#include "common/features.h"
 #include "common/utilities.h"
 
+// Definitions local to the translation unit
+namespace
+{
+
+const char *GetShaderTypeString(GLenum type)
+{
+    switch (type)
+    {
+      case GL_VERTEX_SHADER:
+        return "VERTEX";
+
+      case GL_FRAGMENT_SHADER:
+        return "FRAGMENT";
+
+      default:
+        UNREACHABLE();
+        return "";
+    }
+}
+
+}
+
 namespace rx
 {
 
@@ -44,13 +67,13 @@ const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableLis
     return variableList;
 }
 
-ShaderD3D::ShaderD3D(GLenum type, rx::Renderer *renderer)
+ShaderD3D::ShaderD3D(const gl::Data &data, GLenum type, RendererD3D *renderer)
     : mType(type),
       mRenderer(renderer),
       mShaderVersion(100)
 {
     uncompile();
-    initializeCompiler();
+    initializeCompiler(data);
 }
 
 ShaderD3D::~ShaderD3D()
@@ -69,23 +92,28 @@ const ShaderD3D *ShaderD3D::makeShaderD3D(const ShaderImpl *impl)
     return static_cast<const ShaderD3D*>(impl);
 }
 
+std::string ShaderD3D::getDebugInfo() const
+{
+    return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mType) + " SHADER END\n";
+}
+
 // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
-void ShaderD3D::initializeCompiler()
+void ShaderD3D::initializeCompiler(const gl::Data &data)
 {
     if (!mFragmentCompiler)
     {
-        int result = ShInitialize();
+        bool result = ShInitialize();
 
         if (result)
         {
+            ShShaderSpec specVersion = (data.clientVersion >= 3) ? SH_GLES3_SPEC : SH_GLES2_SPEC;
             ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
 
             ShBuiltInResources resources;
             ShInitBuiltInResources(&resources);
 
-            // TODO(geofflang): use context's caps
-            const gl::Caps &caps = mRenderer->getRendererCaps();
-            const gl::Extensions &extensions = mRenderer->getRendererExtensions();
+            const gl::Caps &caps = *data.caps;
+            const gl::Extensions &extensions = *data.extensions;
 
             resources.MaxVertexAttribs = caps.maxVertexAttributes;
             resources.MaxVertexUniformVectors = caps.maxVertexUniformVectors;
@@ -107,8 +135,8 @@ void ShaderD3D::initializeCompiler()
             resources.MinProgramTexelOffset = caps.minProgramTexelOffset;
             resources.MaxProgramTexelOffset = caps.maxProgramTexelOffset;
 
-            mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
-            mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
+            mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, specVersion, hlslVersion, &resources);
+            mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, specVersion, hlslVersion, &resources);
         }
     }
 }
@@ -126,7 +154,7 @@ void ShaderD3D::releaseCompiler()
 
 void ShaderD3D::parseVaryings(void *compiler)
 {
-     if (!mHlsl.empty())
+    if (!mHlsl.empty())
     {
         const std::vector<sh::Varying> *varyings = ShGetVaryings(compiler);
         ASSERT(varyings);
@@ -183,21 +211,25 @@ void ShaderD3D::uncompile()
     mInterfaceBlocks.clear();
     mActiveAttributes.clear();
     mActiveOutputVariables.clear();
+    mDebugInfo.clear();
 }
 
-void ShaderD3D::compileToHLSL(void *compiler, const std::string &source)
+void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::string &source)
 {
     // ensure the compiler is loaded
-    initializeCompiler();
+    initializeCompiler(data);
 
     int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES);
     std::string sourcePath;
+
+#if !defined (ANGLE_ENABLE_WINDOWS_STORE)
     if (gl::perfActive())
     {
         sourcePath = getTempPath();
         writeFile(sourcePath.c_str(), source.c_str(), source.length());
         compileOptions |= SH_LINE_DIRECTIVES;
     }
+#endif
 
     int result;
     if (sourcePath.empty())
@@ -220,25 +252,20 @@ void ShaderD3D::compileToHLSL(void *compiler, const std::string &source)
         result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH);
     }
 
-    size_t shaderVersion = 100;
-    ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion);
+    mShaderVersion = ShGetShaderVersion(compiler);
 
-    mShaderVersion = static_cast<int>(shaderVersion);
-
-    if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3)
+    if (mShaderVersion == 300 && data.clientVersion < 3)
     {
         mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts";
         TRACE("\n%s", mInfoLog.c_str());
     }
     else if (result)
     {
-        size_t objCodeLen = 0;
-        ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
-
-        char* outputHLSL = new char[objCodeLen];
-        ShGetObjectCode(compiler, outputHLSL);
+        mHlsl = ShGetObjectCode(compiler);
 
 #ifdef _DEBUG
+        // Prefix hlsl shader with commented out glsl shader
+        // Useful in diagnostics tools like pix which capture the hlsl shaders
         std::ostringstream hlslStream;
         hlslStream << "// GLSL\n";
         hlslStream << "//\n";
@@ -254,14 +281,10 @@ void ShaderD3D::compileToHLSL(void *compiler, const std::string &source)
             curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
         }
         hlslStream << "\n\n";
-        hlslStream << outputHLSL;
+        hlslStream << mHlsl;
         mHlsl = hlslStream.str();
-#else
-        mHlsl = outputHLSL;
 #endif
 
-        SafeDeleteArray(outputHLSL);
-
         mUniforms = *GetShaderVariables(ShGetUniforms(compiler));
 
         for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
@@ -271,7 +294,7 @@ void ShaderD3D::compileToHLSL(void *compiler, const std::string &source)
             if (uniform.staticUse)
             {
                 unsigned int index = -1;
-                bool result = ShGetUniformRegister(compiler, uniform.name.c_str(), &index);
+                bool result = ShGetUniformRegister(compiler, uniform.name, &index);
                 UNUSED_ASSERTION_VARIABLE(result);
                 ASSERT(result);
 
@@ -288,7 +311,7 @@ void ShaderD3D::compileToHLSL(void *compiler, const std::string &source)
             if (interfaceBlock.staticUse)
             {
                 unsigned int index = -1;
-                bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name.c_str(), &index);
+                bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index);
                 UNUSED_ASSERTION_VARIABLE(result);
                 ASSERT(result);
 
@@ -298,24 +321,19 @@ void ShaderD3D::compileToHLSL(void *compiler, const std::string &source)
     }
     else
     {
-        size_t infoLogLen = 0;
-        ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
-
-        char* infoLog = new char[infoLogLen];
-        ShGetInfoLog(compiler, infoLog);
-        mInfoLog = infoLog;
+        mInfoLog = ShGetInfoLog(compiler);
 
         TRACE("\n%s", mInfoLog.c_str());
     }
 }
 
-rx::D3DWorkaroundType ShaderD3D::getD3DWorkarounds() const
+D3DWorkaroundType ShaderD3D::getD3DWorkarounds() const
 {
     if (mUsesDiscardRewriting)
     {
         // ANGLE issue 486:
         // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
-        return rx::ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION;
+        return ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION;
     }
 
     if (mUsesNestedBreak)
@@ -323,10 +341,10 @@ rx::D3DWorkaroundType ShaderD3D::getD3DWorkarounds() const
         // ANGLE issue 603:
         // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization
         // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence
-        return rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION;
+        return ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION;
     }
 
-    return rx::ANGLE_D3D_WORKAROUND_NONE;
+    return ANGLE_D3D_WORKAROUND_NONE;
 }
 
 // true if varying x has a higher priority in packing than y
@@ -387,19 +405,16 @@ ShShaderOutput ShaderD3D::getCompilerOutputType(GLenum shader)
       default: UNREACHABLE();  return SH_HLSL9_OUTPUT;
     }
 
-    size_t outputType = 0;
-    ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType);
-
-    return static_cast<ShShaderOutput>(outputType);
+    return ShGetShaderOutputType(compiler);
 }
 
-bool ShaderD3D::compile(const std::string &source)
+bool ShaderD3D::compile(const gl::Data &data, const std::string &source)
 {
     uncompile();
 
     void *compiler = getCompiler();
 
-    compileToHLSL(compiler, source);
+    compileToHLSL(data, compiler, source);
 
     if (mType == GL_VERTEX_SHADER)
     {
@@ -420,6 +435,15 @@ bool ShaderD3D::compile(const std::string &source)
         }
     }
 
+#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
+    mDebugInfo += std::string("// ") + GetShaderTypeString(mType) + " SHADER BEGIN\n";
+    mDebugInfo += "\n// GLSL BEGIN\n\n" + source + "\n\n// GLSL END\n\n\n";
+    mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + getTranslatedSource() + "\n// INITIAL HLSL END\n\n\n";
+    // Successive steps will append more info
+#else
+    mDebugInfo += getTranslatedSource();
+#endif
+
     return !getTranslatedSource().empty();
 }
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h
index 40e64cf36cd..3c9aac2c125 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h
@@ -10,6 +10,7 @@
 #define LIBGLESV2_RENDERER_SHADERD3D_H_
 
 #include "libGLESv2/renderer/ShaderImpl.h"
+#include "libGLESv2/renderer/Workarounds.h"
 #include "libGLESv2/Shader.h"
 
 #include <map>
@@ -17,22 +18,23 @@
 namespace rx
 {
 class DynamicHLSL;
-class Renderer;
+class RendererD3D;
 
 class ShaderD3D : public ShaderImpl
 {
     friend class DynamicHLSL;
 
   public:
-    ShaderD3D(GLenum type, rx::Renderer *renderer);
+    ShaderD3D(const gl::Data &data, GLenum type, RendererD3D *renderer);
     virtual ~ShaderD3D();
 
     static ShaderD3D *makeShaderD3D(ShaderImpl *impl);
     static const ShaderD3D *makeShaderD3D(const ShaderImpl *impl);
 
     // ShaderImpl implementation
-    const std::string &getInfoLog() const { return mInfoLog; }
-    const std::string &getTranslatedSource() const { return mHlsl; }
+    virtual const std::string &getInfoLog() const { return mInfoLog; }
+    virtual const std::string &getTranslatedSource() const { return mHlsl; }
+    virtual std::string getDebugInfo() const;
 
     // D3D-specific methods
     virtual void uncompile();
@@ -40,8 +42,9 @@ class ShaderD3D : public ShaderImpl
     unsigned int getUniformRegister(const std::string &uniformName) const;
     unsigned int getInterfaceBlockRegister(const std::string &blockName) const;
     int getSemanticIndex(const std::string &attributeName) const;
+    void appendDebugInfo(const std::string &info) { mDebugInfo += info; }
 
-    rx::D3DWorkaroundType getD3DWorkarounds() const;
+    D3DWorkaroundType getD3DWorkarounds() const;
     int getShaderVersion() const { return mShaderVersion; }
     bool usesDepthRange() const { return mUsesDepthRange; }
     bool usesPointSize() const { return mUsesPointSize; }
@@ -49,15 +52,15 @@ class ShaderD3D : public ShaderImpl
     static void releaseCompiler();
     static ShShaderOutput getCompilerOutputType(GLenum shader);
 
-    virtual bool compile(const std::string &source);
+    virtual bool compile(const gl::Data &data, const std::string &source);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(ShaderD3D);
 
-    void compileToHLSL(void *compiler, const std::string &source);
+    void compileToHLSL(const gl::Data &data, void *compiler, const std::string &source);
     void parseVaryings(void *compiler);
 
-    void initializeCompiler();
+    void initializeCompiler(const gl::Data &data);
     void parseAttributes(void *compiler);
     void *getCompiler();
 
@@ -67,7 +70,7 @@ class ShaderD3D : public ShaderImpl
     static void *mVertexCompiler;
 
     GLenum mType;
-    rx::Renderer *mRenderer;
+    RendererD3D *mRenderer;
 
     int mShaderVersion;
 
@@ -85,6 +88,7 @@ class ShaderD3D : public ShaderImpl
 
     std::string mHlsl;
     std::string mInfoLog;
+    std::string mDebugInfo;
     std::map<std::string, unsigned int> mUniformRegisterMap;
     std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
 };
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp
index 96c84977cbf..4a67701fdf6 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp
@@ -6,9 +6,6 @@
 
 // TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends.
 
-#include "libGLESv2/renderer/d3d/TextureD3D.h"
-#include "libGLESv2/renderer/d3d/TextureStorage.h"
-#include "libGLESv2/renderer/d3d/ImageD3D.h"
 #include "libGLESv2/Buffer.h"
 #include "libGLESv2/Framebuffer.h"
 #include "libGLESv2/Texture.h"
@@ -16,7 +13,11 @@
 #include "libGLESv2/formatutils.h"
 #include "libGLESv2/renderer/BufferImpl.h"
 #include "libGLESv2/renderer/RenderTarget.h"
-#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/d3d/BufferD3D.h"
+#include "libGLESv2/renderer/d3d/TextureD3D.h"
+#include "libGLESv2/renderer/d3d/TextureStorage.h"
+#include "libGLESv2/renderer/d3d/ImageD3D.h"
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
 
 #include "libEGL/Surface.h"
 
@@ -26,16 +27,51 @@
 namespace rx
 {
 
+namespace
+{
+
+gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const void *pixels, const uint8_t **pointerOut)
+{
+    if (unpack.pixelBuffer.id() != 0)
+    {
+        // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported
+        gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
+        ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
+
+        // TODO: this is the only place outside of renderer that asks for a buffers raw data.
+        // This functionality should be moved into renderer and the getData method of BufferImpl removed.
+        BufferD3D *bufferD3D = BufferD3D::makeBufferD3D(pixelBuffer->getImplementation());
+        ASSERT(bufferD3D);
+        const uint8_t *bufferData = NULL;
+        gl::Error error = bufferD3D->getData(&bufferData);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        *pointerOut = bufferData + offset;
+    }
+    else
+    {
+        *pointerOut = static_cast<const uint8_t *>(pixels);
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
 bool IsRenderTargetUsage(GLenum usage)
 {
     return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
 }
 
-TextureD3D::TextureD3D(Renderer *renderer)
+}
+
+TextureD3D::TextureD3D(RendererD3D *renderer)
     : mRenderer(renderer),
       mUsage(GL_NONE),
       mDirtyImages(true),
-      mImmutable(false)
+      mImmutable(false),
+      mTexStorage(NULL)
 {
 }
 
@@ -54,13 +90,12 @@ TextureStorage *TextureD3D::getNativeTexture()
     // ensure the underlying texture is created
     initializeStorage(false);
 
-    TextureStorage *storage = getBaseLevelStorage();
-    if (storage)
+    if (mTexStorage)
     {
         updateStorage();
     }
 
-    return storage;
+    return mTexStorage;
 }
 
 GLint TextureD3D::getBaseLevelWidth() const
@@ -90,50 +125,79 @@ GLenum TextureD3D::getBaseLevelInternalFormat() const
     return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
 }
 
-void TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, Image *image)
+bool TextureD3D::shouldUseSetData(const Image *image) const
+{
+    if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload)
+    {
+        return false;
+    }
+
+    gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(image->getInternalFormat());
+
+    // We can only handle full updates for depth-stencil textures, so to avoid complications
+    // disable them entirely.
+    if (internalFormat.depthBits > 0 || internalFormat.stencilBits > 0)
+    {
+        return false;
+    }
+
+    // TODO(jmadill): Handle compressed internal formats
+    return (mTexStorage && !internalFormat.compressed);
+}
+
+gl::Error TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, const gl::ImageIndex &index)
 {
+    Image *image = getImage(index);
+    ASSERT(image);
+
     // No-op
     if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
     {
-        return;
+        return gl::Error(GL_NO_ERROR);
     }
 
     // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
     // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
-    const void *pixelData = pixels;
-
-    if (unpack.pixelBuffer.id() != 0)
+    const uint8_t *pixelData = NULL;
+    gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData);
+    if (error.isError())
     {
-        // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported
-        gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
-        ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
-        // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data.
-        // This functionality should be moved into renderer and the getData method of BufferImpl removed.
-        const void *bufferData = pixelBuffer->getImplementation()->getData();
-        pixelData = static_cast<const unsigned char *>(bufferData) + offset;
+        return error;
     }
 
     if (pixelData != NULL)
     {
-        image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData);
+        gl::Error error(GL_NO_ERROR);
+
+        if (shouldUseSetData(image))
+        {
+            error = mTexStorage->setData(index, image, NULL, type, unpack, pixelData);
+        }
+        else
+        {
+            error = image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData);
+        }
+
+        if (error.isError())
+        {
+            return error;
+        }
+
         mDirtyImages = true;
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                          GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index)
+gl::Error TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                               GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index)
 {
-    const void *pixelData = pixels;
-
     // CPU readback & copy where direct GPU copy is not supported
-    if (unpack.pixelBuffer.id() != 0)
+    const uint8_t *pixelData = NULL;
+    gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData);
+    if (error.isError())
     {
-        gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
-        ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
-        // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data.
-        // This functionality should be moved into renderer and the getData method of BufferImpl removed.
-        const void *bufferData = pixelBuffer->getImplementation()->getData();
-        pixelData = static_cast<const unsigned char *>(bufferData) + offset;
+        return error;
     }
 
     if (pixelData != NULL)
@@ -141,32 +205,78 @@ bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei w
         Image *image = getImage(index);
         ASSERT(image);
 
-        image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, type, pixelData);
+        gl::Box region(xoffset, yoffset, zoffset, width, height, depth);
+        if (shouldUseSetData(image))
+        {
+            return mTexStorage->setData(index, image, &region, type, unpack, pixelData);
+        }
+
+        gl::Error error = image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment,
+                                          type, pixelData);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        error = commitRegion(index, region);
+        if (error.isError())
+        {
+            return error;
+        }
+
         mDirtyImages = true;
     }
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)
+gl::Error TextureD3D::setCompressedImage(const gl::PixelUnpackState &unpack, GLsizei imageSize, const void *pixels, Image *image)
 {
-    if (pixels != NULL)
+    // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
+    // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
+    const uint8_t *pixelData = NULL;
+    gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData);
+    if (error.isError())
     {
-        image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixels);
+        return error;
+    }
+
+    if (pixelData != NULL)
+    {
+        gl::Error error = image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixelData);
+        if (error.isError())
+        {
+            return error;
+        }
+
         mDirtyImages = true;
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                                 GLenum format, GLsizei imageSize, const void *pixels, Image *image)
+gl::Error TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                                         GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels, Image *image)
 {
-    if (pixels != NULL)
+    const uint8_t *pixelData = NULL;
+    gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData);
+    if (error.isError())
     {
-        image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixels);
+        return error;
+    }
+
+    if (pixelData != NULL)
+    {
+        gl::Error error = image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixelData);
+        if (error.isError())
+        {
+            return error;
+        }
+
         mDirtyImages = true;
     }
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
 bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat)
@@ -174,21 +284,28 @@ bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum siz
     return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
 }
 
-bool TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
-                               GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget)
+gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
+                                       GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget)
 {
+    // No-op
     if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
     {
-        return true;
+        return gl::Error(GL_NO_ERROR);
     }
 
     // In order to perform the fast copy through the shader, we must have the right format, and be able
     // to create a render target.
     ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat));
 
-    ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
+    uintptr_t offset = reinterpret_cast<uintptr_t>(pixels);
+
+    gl::Error error = mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea);
+    return gl::Error(GL_NO_ERROR);
 }
 
 GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
@@ -210,10 +327,192 @@ int TextureD3D::mipLevels() const
     return gl::log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
 }
 
+TextureStorage *TextureD3D::getStorage()
+{
+    ASSERT(mTexStorage);
+    return mTexStorage;
+}
 
-TextureD3D_2D::TextureD3D_2D(Renderer *renderer)
-    : TextureD3D(renderer),
-      mTexStorage(NULL)
+Image *TextureD3D::getBaseLevelImage() const
+{
+    return getImage(getImageIndex(0, 0));
+}
+
+gl::Error TextureD3D::generateMipmaps()
+{
+    GLint mipCount = mipLevels();
+
+    if (mipCount == 1)
+    {
+        return gl::Error(GL_NO_ERROR); // no-op
+    }
+
+    // Set up proper mipmap chain in our Image array.
+    initMipmapsImages();
+
+    // We know that all layers have the same dimension, for the texture to be complete
+    GLint layerCount = static_cast<GLint>(getLayerCount(0));
+
+    // When making mipmaps with the setData workaround enabled, the texture storage has
+    // the image data already. For non-render-target storage, we have to pull it out into
+    // an image layer.
+    if (mRenderer->getWorkarounds().setDataFasterThanImageUpload && mTexStorage)
+    {
+        if (!mTexStorage->isRenderTarget())
+        {
+            // Copy from the storage mip 0 to Image mip 0
+            for (GLint layer = 0; layer < layerCount; ++layer)
+            {
+                gl::ImageIndex srcIndex = getImageIndex(0, layer);
+
+                Image *image = getImage(srcIndex);
+                gl::Rectangle area(0, 0, image->getWidth(), image->getHeight());
+                gl::Error error = image->copy(0, 0, 0, area, srcIndex, mTexStorage);
+                if (error.isError())
+                {
+                    return error;
+                }
+            }
+        }
+        else
+        {
+            gl::Error error = updateStorage();
+            if (error.isError())
+            {
+                return error;
+            }
+        }
+    }
+
+    bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget());
+
+    for (GLint layer = 0; layer < layerCount; ++layer)
+    {
+        for (GLint mip = 1; mip < mipCount; ++mip)
+        {
+            ASSERT(getLayerCount(mip) == layerCount);
+
+            gl::ImageIndex sourceIndex = getImageIndex(mip - 1, layer);
+            gl::ImageIndex destIndex = getImageIndex(mip, layer);
+
+            if (renderableStorage)
+            {
+                // GPU-side mipmapping
+                gl::Error error = mTexStorage->generateMipmap(sourceIndex, destIndex);
+                if (error.isError())
+                {
+                    return error;
+                }
+            }
+            else
+            {
+                // CPU-side mipmapping
+                gl::Error error = mRenderer->generateMipmap(getImage(destIndex), getImage(sourceIndex));
+                if (error.isError())
+                {
+                    return error;
+                }
+            }
+        }
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+bool TextureD3D::isBaseImageZeroSize() const
+{
+    Image *baseImage = getBaseLevelImage();
+
+    if (!baseImage || baseImage->getWidth() <= 0)
+    {
+        return true;
+    }
+
+    if (!gl::IsCubemapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0)
+    {
+        return true;
+    }
+
+    if (baseImage->getTarget() == GL_TEXTURE_3D && baseImage->getDepth() <= 0)
+    {
+        return true;
+    }
+
+    if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(0) <= 0)
+    {
+        return true;
+    }
+
+    return false;
+}
+
+gl::Error TextureD3D::ensureRenderTarget()
+{
+    gl::Error error = initializeStorage(true);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!isBaseImageZeroSize())
+    {
+        ASSERT(mTexStorage);
+        if (!mTexStorage->isRenderTarget())
+        {
+            TextureStorage *newRenderTargetStorage = NULL;
+            error = createCompleteStorage(true, &newRenderTargetStorage);
+            if (error.isError())
+            {
+                return error;
+            }
+
+            error = mTexStorage->copyToStorage(newRenderTargetStorage);
+            if (error.isError())
+            {
+                SafeDelete(newRenderTargetStorage);
+                return error;
+            }
+
+            error = setCompleteTexStorage(newRenderTargetStorage);
+            if (error.isError())
+            {
+                SafeDelete(newRenderTargetStorage);
+                return error;
+            }
+        }
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const
+{
+    Image *image = getImage(index);
+    bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0)));
+    return (image->isRenderableFormat() && levelsComplete);
+}
+
+gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box &region)
+{
+    if (mTexStorage)
+    {
+        ASSERT(isValidIndex(index));
+        Image *image = getImage(index);
+        ImageD3D *imageD3D = ImageD3D::makeImageD3D(image);
+        gl::Error error = imageD3D->copyToStorage(mTexStorage, index, region);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        image->markClean();
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+TextureD3D_2D::TextureD3D_2D(RendererD3D *renderer)
+    : TextureD3D(renderer)
 {
     for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
     {
@@ -292,7 +591,9 @@ bool TextureD3D_2D::isDepth(GLint level) const
     return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
-void TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth,
+                                  GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack,
+                                  const void *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D && depth == 1);
 
@@ -302,142 +603,209 @@ void TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLsizei
 
     redefineImage(level, sizedInternalFormat, width, height);
 
+    gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+
     // Attempt a fast gpu copy of the pixel data to the surface
     if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level))
     {
-        gl::ImageIndex index = gl::ImageIndex::Make2D(level);
-
         // Will try to create RT storage if it does not exist
-        RenderTarget *destRenderTarget = getRenderTarget(index);
+        RenderTarget *destRenderTarget = NULL;
+        gl::Error error = getRenderTarget(index, &destRenderTarget);
+        if (error.isError())
+        {
+            return error;
+        }
+
         gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
 
-        if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget))
+        error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget);
+        if (error.isError())
         {
-            // Ensure we don't overwrite our newly initialized data
-            mImageArray[level]->markClean();
-
-            fastUnpacked = true;
+            return error;
         }
+
+        // Ensure we don't overwrite our newly initialized data
+        mImageArray[level]->markClean();
+
+        fastUnpacked = true;
     }
 
     if (!fastUnpacked)
     {
-        TextureD3D::setImage(unpack, type, pixels, mImageArray[level]);
+        gl::Error error = TextureD3D::setImage(unpack, type, pixels, index);
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2D::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+gl::Error TextureD3D_2D::setCompressedImage(GLenum target, GLint level, GLenum format,
+                                            GLsizei width, GLsizei height, GLsizei depth,
+                                            GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D && depth == 1);
 
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
     redefineImage(level, format, width, height);
 
-    TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]);
+    return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[level]);
 }
 
-void TextureD3D_2D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_2D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                  GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
+                                  const gl::PixelUnpackState &unpack, const void *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0);
 
     bool fastUnpacked = false;
 
     gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+    gl::Box destArea(xoffset, yoffset, 0, width, height, 1);
     if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
     {
-        RenderTarget *renderTarget = getRenderTarget(index);
-        gl::Box destArea(xoffset, yoffset, 0, width, height, 1);
-
-        if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget))
+        RenderTarget *renderTarget = NULL;
+        gl::Error error = getRenderTarget(index, &renderTarget);
+        if (error.isError())
         {
-            // Ensure we don't overwrite our newly initialized data
-            mImageArray[level]->markClean();
+            return error;
+        }
 
-            fastUnpacked = true;
+        error = fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget);
+        if (error.isError())
+        {
+            return error;
         }
+
+        // Ensure we don't overwrite our newly initialized data
+        mImageArray[level]->markClean();
+
+        fastUnpacked = true;
     }
 
-    if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index))
+    if (!fastUnpacked)
     {
-        commitRect(level, xoffset, yoffset, width, height);
+        return TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type,
+                                    unpack, pixels, index);
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
+gl::Error TextureD3D_2D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                            GLsizei width, GLsizei height, GLsizei depth, GLenum format,
+                                            GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0);
 
-    if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[level]))
+    gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels, mImageArray[level]);
+    if (error.isError())
     {
-        commitRect(level, xoffset, yoffset, width, height);
+        return error;
     }
+
+    gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+    gl::Box region(xoffset, yoffset, 0, width, height, 1);
+    return commitRegion(index, region);
 }
 
-void TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height,
+                                   gl::Framebuffer *source)
 {
     ASSERT(target == GL_TEXTURE_2D);
 
     GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
     redefineImage(level, sizedInternalFormat, width, height);
 
-    if (!mImageArray[level]->isRenderableFormat())
+    gl::Rectangle sourceRect(x, y, width, height);
+    gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+
+    if (!canCreateRenderTargetForImage(index))
     {
-        mImageArray[level]->copy(0, 0, 0, x, y, width, height, source);
+        gl::Error error = mImageArray[level]->copy(0, 0, 0, sourceRect, source);
+        if (error.isError())
+        {
+            return error;
+        }
+
         mDirtyImages = true;
     }
     else
     {
-        ensureRenderTarget();
+        gl::Error error = ensureRenderTarget();
+        if (error.isError())
+        {
+            return error;
+        }
+
         mImageArray[level]->markClean();
 
         if (width != 0 && height != 0 && isValidLevel(level))
         {
-            gl::Rectangle sourceRect;
-            sourceRect.x = x;
-            sourceRect.width = width;
-            sourceRect.y = y;
-            sourceRect.height = height;
-
-            mRenderer->copyImage2D(source, sourceRect, format, 0, 0, mTexStorage, level);
+            gl::Error error = mRenderer->copyImage2D(source, sourceRect, format, 0, 0, mTexStorage, level);
+            if (error.isError())
+            {
+                return error;
+            }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                      GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
 {
     ASSERT(target == GL_TEXTURE_2D && zoffset == 0);
 
     // can only make our texture storage to a render target if level 0 is defined (with a width & height) and
     // the current level we're copying to is defined (with appropriate format, width & height)
-    bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
 
-    if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
+    gl::Rectangle sourceRect(x, y, width, height);
+    gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+
+    if (!canCreateRenderTargetForImage(index))
     {
-        mImageArray[level]->copy(xoffset, yoffset, 0, x, y, width, height, source);
+        gl::Error error = mImageArray[level]->copy(xoffset, yoffset, 0, sourceRect, source);
+        if (error.isError())
+        {
+            return error;
+        }
+
         mDirtyImages = true;
     }
     else
     {
-        ensureRenderTarget();
+        gl::Error error = ensureRenderTarget();
+        if (error.isError())
+        {
+            return error;
+        }
 
         if (isValidLevel(level))
         {
-            updateStorageLevel(level);
-
-            gl::Rectangle sourceRect;
-            sourceRect.x = x;
-            sourceRect.width = width;
-            sourceRect.y = y;
-            sourceRect.height = height;
+            error = updateStorageLevel(level);
+            if (error.isError())
+            {
+                return error;
+            }
 
-            mRenderer->copyImage2D(source, sourceRect,
-                                   gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
-                                   xoffset, yoffset, mTexStorage, level);
+            error = mRenderer->copyImage2D(source, sourceRect,
+                                           gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
+                                           xoffset, yoffset, mTexStorage, level);
+            if (error.isError())
+            {
+                return error;
+            }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+gl::Error TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
 {
     ASSERT(target == GL_TEXTURE_2D && depth == 1);
 
@@ -453,11 +821,20 @@ void TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalformat
         mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
     }
 
-    mImmutable = true;
-
+    // TODO(geofflang): Verify storage creation had no errors
     bool renderTarget = IsRenderTargetUsage(mUsage);
     TextureStorage *storage = mRenderer->createTextureStorage2D(internalformat, renderTarget, width, height, levels);
-    setCompleteTexStorage(storage);
+
+    gl::Error error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
+    mImmutable = true;
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 void TextureD3D_2D::bindTexImage(egl::Surface *surface)
@@ -489,7 +866,7 @@ void TextureD3D_2D::releaseTexImage()
     }
 }
 
-void TextureD3D_2D::generateMipmaps()
+void TextureD3D_2D::initMipmapsImages()
 {
     // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
     int levelCount = mipLevels();
@@ -499,42 +876,32 @@ void TextureD3D_2D::generateMipmaps()
                       std::max(getBaseLevelWidth() >> level, 1),
                       std::max(getBaseLevelHeight() >> level, 1));
     }
-
-    if (mTexStorage && mTexStorage->isRenderTarget())
-    {
-        mTexStorage->generateMipmaps();
-        for (int level = 1; level < levelCount; level++)
-        {
-            mImageArray[level]->markClean();
-        }
-    }
-    else
-    {
-        for (int level = 1; level < levelCount; level++)
-        {
-            mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]);
-        }
-    }
 }
 
 unsigned int TextureD3D_2D::getRenderTargetSerial(const gl::ImageIndex &index)
 {
     ASSERT(!index.hasLayer());
-    return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0);
+    return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
 }
 
-RenderTarget *TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index)
+gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
 {
     ASSERT(!index.hasLayer());
 
     // ensure the underlying texture is created
-    if (!ensureRenderTarget())
+    gl::Error error = ensureRenderTarget();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = updateStorageLevel(index.mipIndex);
+    if (error.isError())
     {
-        return NULL;
+        return error;
     }
 
-    updateStorageLevel(index.mipIndex);
-    return mTexStorage->getRenderTarget(index);
+    return mTexStorage->getRenderTarget(index, outRT);
 }
 
 bool TextureD3D_2D::isValidLevel(int level) const
@@ -586,31 +953,55 @@ bool TextureD3D_2D::isLevelComplete(int level) const
     return true;
 }
 
+bool TextureD3D_2D::isImageComplete(const gl::ImageIndex &index) const
+{
+    return isLevelComplete(index.mipIndex);
+}
+
 // Constructs a native texture resource from the texture images
-void TextureD3D_2D::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_2D::initializeStorage(bool renderTarget)
 {
     // Only initialize the first time this texture is used as a render target or shader resource
     if (mTexStorage)
     {
-        return;
+        return gl::Error(GL_NO_ERROR);
     }
 
     // do not attempt to create storage for nonexistant data
     if (!isLevelComplete(0))
     {
-        return;
+        return gl::Error(GL_NO_ERROR);
     }
 
     bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
 
-    setCompleteTexStorage(createCompleteStorage(createRenderTarget));
+    TextureStorage *storage = NULL;
+    gl::Error error = createCompleteStorage(createRenderTarget, &storage);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
     ASSERT(mTexStorage);
 
     // flush image data to the storage
-    updateStorage();
+    error = updateStorage();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-TextureStorage *TextureD3D_2D::createCompleteStorage(bool renderTarget) const
+gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const
 {
     GLsizei width = getBaseLevelWidth();
     GLsizei height = getBaseLevelHeight();
@@ -621,26 +1012,35 @@ TextureStorage *TextureD3D_2D::createCompleteStorage(bool renderTarget) const
     // use existing storage level count, when previously specified by TexStorage*D
     GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
 
-    return mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels);
+    // TODO(geofflang): Determine if the texture creation succeeded
+    *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels);
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
 {
-    SafeDelete(mTexStorage);
-    mTexStorage = newCompleteTexStorage;
-
-    if (mTexStorage && mTexStorage->isManaged())
+    if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
     {
-        for (int level = 0; level < mTexStorage->getLevelCount(); level++)
+        for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
         {
-            mImageArray[level]->setManagedSurface2D(mTexStorage, level);
+            gl::Error error = mImageArray[level]->setManagedSurface2D(newCompleteTexStorage, level);
+            if (error.isError())
+            {
+                return error;
+            }
         }
     }
 
+    SafeDelete(mTexStorage);
+    mTexStorage = newCompleteTexStorage;
+
     mDirtyImages = true;
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2D::updateStorage()
+gl::Error TextureD3D_2D::updateStorage()
 {
     ASSERT(mTexStorage != NULL);
     GLint storageLevels = mTexStorage->getLevelCount();
@@ -648,54 +1048,34 @@ void TextureD3D_2D::updateStorage()
     {
         if (mImageArray[level]->isDirty() && isLevelComplete(level))
         {
-            updateStorageLevel(level);
-        }
-    }
-}
-
-bool TextureD3D_2D::ensureRenderTarget()
-{
-    initializeStorage(true);
-
-    if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0)
-    {
-        ASSERT(mTexStorage);
-        if (!mTexStorage->isRenderTarget())
-        {
-            TextureStorage *newRenderTargetStorage = createCompleteStorage(true);
-
-            if (!mRenderer->copyToRenderTarget2D(newRenderTargetStorage, mTexStorage))
+            gl::Error error = updateStorageLevel(level);
+            if (error.isError())
             {
-                delete newRenderTargetStorage;
-                return gl::error(GL_OUT_OF_MEMORY, false);
+                return error;
             }
-
-            setCompleteTexStorage(newRenderTargetStorage);
         }
     }
 
-    return (mTexStorage && mTexStorage->isRenderTarget());
+    return gl::Error(GL_NO_ERROR);
 }
 
-TextureStorage *TextureD3D_2D::getBaseLevelStorage()
-{
-    return mTexStorage;
-}
-
-const ImageD3D *TextureD3D_2D::getBaseLevelImage() const
-{
-    return mImageArray[0];
-}
-
-void TextureD3D_2D::updateStorageLevel(int level)
+gl::Error TextureD3D_2D::updateStorageLevel(int level)
 {
     ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
     ASSERT(isLevelComplete(level));
 
     if (mImageArray[level]->isDirty())
     {
-        commitRect(level, 0, 0, getWidth(level), getHeight(level));
+        gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+        gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
+        gl::Error error = commitRegion(index, region);
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height)
@@ -727,22 +1107,25 @@ void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei wi
     }
 }
 
-void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+gl::ImageIndexIterator TextureD3D_2D::imageIterator() const
 {
-    if (isValidLevel(level))
-    {
-        ImageD3D *image = mImageArray[level];
-        if (image->copyToStorage2D(mTexStorage, level, xoffset, yoffset, width, height))
-        {
-            image->markClean();
-        }
-    }
+    return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount());
 }
 
+gl::ImageIndex TextureD3D_2D::getImageIndex(GLint mip, GLint /*layer*/) const
+{
+    // "layer" does not apply to 2D Textures.
+    return gl::ImageIndex::Make2D(mip);
+}
 
-TextureD3D_Cube::TextureD3D_Cube(Renderer *renderer)
-    : TextureD3D(renderer),
-      mTexStorage(NULL)
+bool TextureD3D_2D::isValidIndex(const gl::ImageIndex &index) const
+{
+    return (mTexStorage && index.type == GL_TEXTURE_2D &&
+            index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
+}
+
+TextureD3D_Cube::TextureD3D_Cube(RendererD3D *renderer)
+    : TextureD3D(renderer)
 {
     for (int i = 0; i < 6; i++)
     {
@@ -802,19 +1185,23 @@ bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const
     return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0;
 }
 
-void TextureD3D_Cube::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_Cube::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth,
+                                    GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack,
+                                    const void *pixels)
 {
     ASSERT(depth == 1);
 
-    int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
     GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
 
-    redefineImage(faceIndex, level, sizedInternalFormat, width, height);
+    redefineImage(index.layerIndex, level, sizedInternalFormat, width, height);
 
-    TextureD3D::setImage(unpack, type, pixels, mImageArray[faceIndex][level]);
+    return TextureD3D::setImage(unpack, type, pixels, index);
 }
 
-void TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format,
+                                              GLsizei width, GLsizei height, GLsizei depth,
+                                              GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
 {
     ASSERT(depth == 1);
 
@@ -823,101 +1210,129 @@ void TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum form
 
     redefineImage(faceIndex, level, format, width, height);
 
-    TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[faceIndex][level]);
+    return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[faceIndex][level]);
 }
 
-void TextureD3D_Cube::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_Cube::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                    GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
+                                    const gl::PixelUnpackState &unpack, const void *pixels)
 {
     ASSERT(depth == 1 && zoffset == 0);
-
-    int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
-
     gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
-    if (TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index))
-    {
-        commitRect(faceIndex, level, xoffset, yoffset, width, height);
-    }
+    return TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index);
 }
 
-void TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
+gl::Error TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                              GLsizei width, GLsizei height, GLsizei depth, GLenum format,
+                                              GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
 {
     ASSERT(depth == 1 && zoffset == 0);
 
-    int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
+    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
 
-    if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[faceIndex][level]))
+    gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels, mImageArray[index.layerIndex][level]);
+    if (error.isError())
     {
-        commitRect(faceIndex, level, xoffset, yoffset, width, height);
+        return error;
     }
+
+    gl::Box region(xoffset, yoffset, 0, width, height, 1);
+    return commitRegion(index, region);
 }
 
-void TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y,
+                                     GLsizei width, GLsizei height, gl::Framebuffer *source)
 {
     int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
     GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
 
     redefineImage(faceIndex, level, sizedInternalFormat, width, height);
 
-    if (!mImageArray[faceIndex][level]->isRenderableFormat())
+    gl::Rectangle sourceRect(x, y, width, height);
+    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
+
+    if (!canCreateRenderTargetForImage(index))
     {
-        mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source);
+        gl::Error error = mImageArray[faceIndex][level]->copy(0, 0, 0, sourceRect, source);
+        if (error.isError())
+        {
+            return error;
+        }
+
         mDirtyImages = true;
     }
     else
     {
-        ensureRenderTarget();
+        gl::Error error = ensureRenderTarget();
+        if (error.isError())
+        {
+            return error;
+        }
+
         mImageArray[faceIndex][level]->markClean();
 
         ASSERT(width == height);
 
         if (width > 0 && isValidFaceLevel(faceIndex, level))
         {
-            gl::Rectangle sourceRect;
-            sourceRect.x = x;
-            sourceRect.width = width;
-            sourceRect.y = y;
-            sourceRect.height = height;
-
-            mRenderer->copyImageCube(source, sourceRect, format, 0, 0, mTexStorage, target, level);
+            error = mRenderer->copyImageCube(source, sourceRect, format, 0, 0, mTexStorage, target, level);
+            if (error.isError())
+            {
+                return error;
+            }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                        GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
 {
     int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
 
-    // We can only make our texture storage to a render target if the level we're copying *to* is complete
-    // and the base level is cube-complete. The base level must be cube complete (common case) because we cannot
-    // rely on the "getBaseLevel*" methods reliably otherwise.
-    bool canCreateRenderTarget = isFaceLevelComplete(faceIndex, level) && isCubeComplete();
+    gl::Rectangle sourceRect(x, y, width, height);
+    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
 
-    if (!mImageArray[faceIndex][level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
+    if (!canCreateRenderTargetForImage(index))
     {
-        mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source);
+        gl::Error error =mImageArray[faceIndex][level]->copy(0, 0, 0, sourceRect, source);
+        if (error.isError())
+        {
+            return error;
+        }
+
         mDirtyImages = true;
     }
     else
     {
-        ensureRenderTarget();
+        gl::Error error = ensureRenderTarget();
+        if (error.isError())
+        {
+            return error;
+        }
 
         if (isValidFaceLevel(faceIndex, level))
         {
-            updateStorageFaceLevel(faceIndex, level);
-
-            gl::Rectangle sourceRect;
-            sourceRect.x = x;
-            sourceRect.width = width;
-            sourceRect.y = y;
-            sourceRect.height = height;
+            error = updateStorageFaceLevel(faceIndex, level);
+            if (error.isError())
+            {
+                return error;
+            }
 
-            mRenderer->copyImageCube(source, sourceRect, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
-                                     xoffset, yoffset, mTexStorage, target, level);
+            error = mRenderer->copyImageCube(source, sourceRect, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
+                                             xoffset, yoffset, mTexStorage, target, level);
+            if (error.isError())
+            {
+                return error;
+            }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+gl::Error TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
 {
     ASSERT(width == height);
     ASSERT(depth == 1);
@@ -939,11 +1354,20 @@ void TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum internalform
         }
     }
 
-    mImmutable = true;
-
+    // TODO(geofflang): Verify storage creation had no errors
     bool renderTarget = IsRenderTargetUsage(mUsage);
     TextureStorage *storage = mRenderer->createTextureStorageCube(internalformat, renderTarget, width, levels);
-    setCompleteTexStorage(storage);
+
+    gl::Error error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
+    mImmutable = true;
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
@@ -984,7 +1408,7 @@ void TextureD3D_Cube::releaseTexImage()
 }
 
 
-void TextureD3D_Cube::generateMipmaps()
+void TextureD3D_Cube::initMipmapsImages()
 {
     // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
     int levelCount = mipLevels();
@@ -996,74 +1420,76 @@ void TextureD3D_Cube::generateMipmaps()
             redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), faceLevelSize, faceLevelSize);
         }
     }
-
-    if (mTexStorage && mTexStorage->isRenderTarget())
-    {
-        mTexStorage->generateMipmaps();
-
-        for (int faceIndex = 0; faceIndex < 6; faceIndex++)
-        {
-            for (int level = 1; level < levelCount; level++)
-            {
-                mImageArray[faceIndex][level]->markClean();
-            }
-        }
-    }
-    else
-    {
-        for (int faceIndex = 0; faceIndex < 6; faceIndex++)
-        {
-            for (int level = 1; level < levelCount; level++)
-            {
-                mRenderer->generateMipmap(mImageArray[faceIndex][level], mImageArray[faceIndex][level - 1]);
-            }
-        }
-    }
 }
 
 unsigned int TextureD3D_Cube::getRenderTargetSerial(const gl::ImageIndex &index)
 {
-    return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0);
+    return (ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
 }
 
-RenderTarget *TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index)
+gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
 {
     ASSERT(gl::IsCubemapTextureTarget(index.type));
 
     // ensure the underlying texture is created
-    if (!ensureRenderTarget())
+    gl::Error error = ensureRenderTarget();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = updateStorageFaceLevel(index.layerIndex, index.mipIndex);
+    if (error.isError())
     {
-        return NULL;
+        return error;
     }
 
-    updateStorageFaceLevel(index.layerIndex, index.mipIndex);
-    return mTexStorage->getRenderTarget(index);
+    return mTexStorage->getRenderTarget(index, outRT);
 }
 
-void TextureD3D_Cube::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_Cube::initializeStorage(bool renderTarget)
 {
     // Only initialize the first time this texture is used as a render target or shader resource
     if (mTexStorage)
     {
-        return;
+        return gl::Error(GL_NO_ERROR);
     }
 
     // do not attempt to create storage for nonexistant data
     if (!isFaceLevelComplete(0, 0))
     {
-        return;
+        return gl::Error(GL_NO_ERROR);
     }
 
     bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
 
-    setCompleteTexStorage(createCompleteStorage(createRenderTarget));
+    TextureStorage *storage = NULL;
+    gl::Error error = createCompleteStorage(createRenderTarget, &storage);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
     ASSERT(mTexStorage);
 
     // flush image data to the storage
-    updateStorage();
+    error = updateStorage();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-TextureStorage *TextureD3D_Cube::createCompleteStorage(bool renderTarget) const
+gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const
 {
     GLsizei size = getBaseLevelWidth();
 
@@ -1072,29 +1498,37 @@ TextureStorage *TextureD3D_Cube::createCompleteStorage(bool renderTarget) const
     // use existing storage level count, when previously specified by TexStorage*D
     GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1));
 
-    return mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels);
+    // TODO (geofflang): detect if storage creation succeeded
+    *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels);
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
 {
-    SafeDelete(mTexStorage);
-    mTexStorage = newCompleteTexStorage;
-
-    if (mTexStorage && mTexStorage->isManaged())
+    if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
     {
         for (int faceIndex = 0; faceIndex < 6; faceIndex++)
         {
-            for (int level = 0; level < mTexStorage->getLevelCount(); level++)
+            for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
             {
-                mImageArray[faceIndex][level]->setManagedSurfaceCube(mTexStorage, faceIndex, level);
+                gl::Error error = mImageArray[faceIndex][level]->setManagedSurfaceCube(newCompleteTexStorage, faceIndex, level);
+                if (error.isError())
+                {
+                    return error;
+                }
             }
         }
     }
 
+    SafeDelete(mTexStorage);
+    mTexStorage = newCompleteTexStorage;
+
     mDirtyImages = true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_Cube::updateStorage()
+gl::Error TextureD3D_Cube::updateStorage()
 {
     ASSERT(mTexStorage != NULL);
     GLint storageLevels = mTexStorage->getLevelCount();
@@ -1104,46 +1538,16 @@ void TextureD3D_Cube::updateStorage()
         {
             if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level))
             {
-                updateStorageFaceLevel(face, level);
-            }
-        }
-    }
-}
-
-bool TextureD3D_Cube::ensureRenderTarget()
-{
-    initializeStorage(true);
-
-    if (getBaseLevelWidth() > 0)
-    {
-        ASSERT(mTexStorage);
-        if (!mTexStorage->isRenderTarget())
-        {
-            TextureStorage *newRenderTargetStorage = createCompleteStorage(true);
-
-            if (!mRenderer->copyToRenderTargetCube(newRenderTargetStorage, mTexStorage))
-            {
-                delete newRenderTargetStorage;
-                return gl::error(GL_OUT_OF_MEMORY, false);
+                gl::Error error = updateStorageFaceLevel(face, level);
+                if (error.isError())
+                {
+                    return error;
+                }
             }
-
-            setCompleteTexStorage(newRenderTargetStorage);
         }
     }
 
-    return (mTexStorage && mTexStorage->isRenderTarget());
-}
-
-TextureStorage *TextureD3D_Cube::getBaseLevelStorage()
-{
-    return mTexStorage;
-}
-
-const ImageD3D *TextureD3D_Cube::getBaseLevelImage() const
-{
-    // Note: if we are not cube-complete, there is no single base level image that can describe all
-    // cube faces, so this method is only well-defined for a cube-complete base level.
-    return mImageArray[0][0];
+    return gl::Error(GL_NO_ERROR);
 }
 
 bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const
@@ -1191,15 +1595,29 @@ bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const
     return true;
 }
 
-void TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level)
+bool TextureD3D_Cube::isImageComplete(const gl::ImageIndex &index) const
+{
+    return isFaceLevelComplete(index.layerIndex, index.mipIndex);
+}
+
+gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level)
 {
     ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL);
     ImageD3D *image = mImageArray[faceIndex][level];
 
     if (image->isDirty())
     {
-        commitRect(faceIndex, level, 0, 0, image->getWidth(), image->getHeight());
+        GLenum faceTarget = gl::TextureCubeMap::layerIndexToTarget(faceIndex);
+        gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level);
+        gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1);
+        gl::Error error = commitRegion(index, region);
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height)
@@ -1235,20 +1653,25 @@ void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalf
     }
 }
 
-void TextureD3D_Cube::commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const
 {
-    if (isValidFaceLevel(faceIndex, level))
-    {
-        ImageD3D *image = mImageArray[faceIndex][level];
-        if (image->copyToStorageCube(mTexStorage, faceIndex, level, xoffset, yoffset, width, height))
-            image->markClean();
-    }
+    return gl::ImageIndexIterator::MakeCube(0, mTexStorage->getLevelCount());
+}
+
+gl::ImageIndex TextureD3D_Cube::getImageIndex(GLint mip, GLint layer) const
+{
+    // The "layer" of the image index corresponds to the cube face
+    return gl::ImageIndex::MakeCube(gl::TextureCubeMap::layerIndexToTarget(layer), mip);
 }
 
+bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const
+{
+    return (mTexStorage && gl::IsCubemapTextureTarget(index.type) &&
+            index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
+}
 
-TextureD3D_3D::TextureD3D_3D(Renderer *renderer)
-    : TextureD3D(renderer),
-      mTexStorage(NULL)
+TextureD3D_3D::TextureD3D_3D(RendererD3D *renderer)
+    : TextureD3D(renderer)
 {
     for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
     {
@@ -1327,7 +1750,9 @@ bool TextureD3D_3D::isDepth(GLint level) const
     return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
-void TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth,
+                                  GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack,
+                                  const void *pixels)
 {
     ASSERT(target == GL_TEXTURE_3D);
     GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
@@ -1336,40 +1761,60 @@ void TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLsizei
 
     bool fastUnpacked = false;
 
+    gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+
     // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
     if (isFastUnpackable(unpack, sizedInternalFormat))
     {
         // Will try to create RT storage if it does not exist
-        gl::ImageIndex index = gl::ImageIndex::Make3D(level);
-        RenderTarget *destRenderTarget = getRenderTarget(index);
+        RenderTarget *destRenderTarget = NULL;
+        gl::Error error = getRenderTarget(index, &destRenderTarget);
+        if (error.isError())
+        {
+            return error;
+        }
+
         gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
 
-        if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget))
+        error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget);
+        if (error.isError())
         {
-            // Ensure we don't overwrite our newly initialized data
-            mImageArray[level]->markClean();
-
-            fastUnpacked = true;
+            return error;
         }
+
+        // Ensure we don't overwrite our newly initialized data
+        mImageArray[level]->markClean();
+
+        fastUnpacked = true;
     }
 
     if (!fastUnpacked)
     {
-        TextureD3D::setImage(unpack, type, pixels, mImageArray[level]);
+        gl::Error error = TextureD3D::setImage(unpack, type, pixels, index);
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_3D::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+gl::Error TextureD3D_3D::setCompressedImage(GLenum target, GLint level, GLenum format,
+                                            GLsizei width, GLsizei height,GLsizei depth,
+                                            GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
 {
     ASSERT(target == GL_TEXTURE_3D);
 
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
     redefineImage(level, format, width, height, depth);
 
-    TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]);
+    return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[level]);
 }
 
-void TextureD3D_3D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_3D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                  GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
+                                  const gl::PixelUnpackState &unpack, const void *pixels)
 {
     ASSERT(target == GL_TEXTURE_3D);
 
@@ -1380,74 +1825,108 @@ void TextureD3D_3D::subImage(GLenum target, GLint level, GLint xoffset, GLint yo
     // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
     if (isFastUnpackable(unpack, getInternalFormat(level)))
     {
-        RenderTarget *destRenderTarget = getRenderTarget(index);
-        gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth);
-
-        if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget))
+        RenderTarget *destRenderTarget = NULL;
+        gl::Error error = getRenderTarget(index, &destRenderTarget);
+        if (error.isError())
         {
-            // Ensure we don't overwrite our newly initialized data
-            mImageArray[level]->markClean();
+            return error;
+        }
 
-            fastUnpacked = true;
+        gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth);
+        error = fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget);
+        if (error.isError())
+        {
+            return error;
         }
+
+        // Ensure we don't overwrite our newly initialized data
+        mImageArray[level]->markClean();
+
+        fastUnpacked = true;
     }
 
-    if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, index))
+    if (!fastUnpacked)
     {
-        commitRect(level, xoffset, yoffset, zoffset, width, height, depth);
+        return TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type,
+                                    unpack, pixels, index);
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_3D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
+gl::Error TextureD3D_3D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                            GLsizei width, GLsizei height, GLsizei depth, GLenum format,
+                                            GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
 {
     ASSERT(target == GL_TEXTURE_3D);
 
-    if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, mImageArray[level]))
+    gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth,
+                                                     format, imageSize, unpack, pixels, mImageArray[level]);
+    if (error.isError())
     {
-        commitRect(level, xoffset, yoffset, zoffset, width, height, depth);
+        return error;
     }
+
+    gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+    gl::Box region(xoffset, yoffset, zoffset, width, height, depth);
+    return commitRegion(index, region);
 }
 
-void TextureD3D_3D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_3D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y,
+                                   GLsizei width, GLsizei height, gl::Framebuffer *source)
 {
     UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented.");
 }
 
-void TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                      GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
 {
     ASSERT(target == GL_TEXTURE_3D);
 
-    // can only make our texture storage to a render target if level 0 is defined (with a width & height) and
-    // the current level we're copying to is defined (with appropriate format, width & height)
-    bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
+    gl::Rectangle sourceRect(x, y, width, height);
+    gl::ImageIndex index = gl::ImageIndex::Make3D(level);
 
-    if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
+    if (canCreateRenderTargetForImage(index))
     {
-        mImageArray[level]->copy(xoffset, yoffset, zoffset, x, y, width, height, source);
+        gl::Error error = mImageArray[level]->copy(xoffset, yoffset, zoffset, sourceRect, source);
+        if (error.isError())
+        {
+            return error;
+        }
+
         mDirtyImages = true;
     }
     else
     {
-        ensureRenderTarget();
+        gl::Error error = ensureRenderTarget();
+        if (error.isError())
+        {
+            return error;
+        }
 
         if (isValidLevel(level))
         {
-            updateStorageLevel(level);
-
-            gl::Rectangle sourceRect;
-            sourceRect.x = x;
-            sourceRect.width = width;
-            sourceRect.y = y;
-            sourceRect.height = height;
+            error = updateStorageLevel(level);
+            if (error.isError())
+            {
+                return error;
+            }
 
-            mRenderer->copyImage3D(source, sourceRect,
-                                   gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
-                                   xoffset, yoffset, zoffset, mTexStorage, level);
+            error = mRenderer->copyImage3D(source, sourceRect,
+                                           gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
+                                           xoffset, yoffset, zoffset, mTexStorage, level);
+            if (error.isError())
+            {
+                return error;
+            }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+gl::Error TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
 {
     ASSERT(target == GL_TEXTURE_3D);
 
@@ -1464,11 +1943,20 @@ void TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalformat
         mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true);
     }
 
-    mImmutable = true;
-
+    // TODO(geofflang): Verify storage creation had no errors
     bool renderTarget = IsRenderTargetUsage(mUsage);
     TextureStorage *storage = mRenderer->createTextureStorage3D(internalformat, renderTarget, width, height, depth, levels);
-    setCompleteTexStorage(storage);
+
+    gl::Error error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
+    mImmutable = true;
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 void TextureD3D_3D::bindTexImage(egl::Surface *surface)
@@ -1482,7 +1970,7 @@ void TextureD3D_3D::releaseTexImage()
 }
 
 
-void TextureD3D_3D::generateMipmaps()
+void TextureD3D_3D::initMipmapsImages()
 {
     // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
     int levelCount = mipLevels();
@@ -1493,74 +1981,85 @@ void TextureD3D_3D::generateMipmaps()
                       std::max(getBaseLevelHeight() >> level, 1),
                       std::max(getBaseLevelDepth() >> level, 1));
     }
-
-    if (mTexStorage && mTexStorage->isRenderTarget())
-    {
-        mTexStorage->generateMipmaps();
-
-        for (int level = 1; level < levelCount; level++)
-        {
-            mImageArray[level]->markClean();
-        }
-    }
-    else
-    {
-        for (int level = 1; level < levelCount; level++)
-        {
-            mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]);
-        }
-    }
 }
 
 unsigned int TextureD3D_3D::getRenderTargetSerial(const gl::ImageIndex &index)
 {
-    return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0);
+    return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
 }
 
-RenderTarget *TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index)
+gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
 {
     // ensure the underlying texture is created
-    if (!ensureRenderTarget())
+    gl::Error error = ensureRenderTarget();
+    if (error.isError())
     {
-        return NULL;
+        return error;
     }
 
     if (index.hasLayer())
     {
-        updateStorage();
+        error = updateStorage();
+        if (error.isError())
+        {
+            return error;
+        }
     }
     else
     {
-        updateStorageLevel(index.mipIndex);
+        error = updateStorageLevel(index.mipIndex);
+        if (error.isError())
+        {
+            return error;
+        }
     }
 
-    return mTexStorage->getRenderTarget(index);
+    return mTexStorage->getRenderTarget(index, outRT);
 }
 
-void TextureD3D_3D::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_3D::initializeStorage(bool renderTarget)
 {
     // Only initialize the first time this texture is used as a render target or shader resource
     if (mTexStorage)
     {
-        return;
+        return gl::Error(GL_NO_ERROR);
     }
 
     // do not attempt to create storage for nonexistant data
     if (!isLevelComplete(0))
     {
-        return;
+        return gl::Error(GL_NO_ERROR);
     }
 
     bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
 
-    setCompleteTexStorage(createCompleteStorage(createRenderTarget));
+    TextureStorage *storage = NULL;
+    gl::Error error = createCompleteStorage(createRenderTarget, &storage);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
     ASSERT(mTexStorage);
 
     // flush image data to the storage
-    updateStorage();
+    error = updateStorage();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-TextureStorage *TextureD3D_3D::createCompleteStorage(bool renderTarget) const
+gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const
 {
     GLsizei width = getBaseLevelWidth();
     GLsizei height = getBaseLevelHeight();
@@ -1572,10 +2071,13 @@ TextureStorage *TextureD3D_3D::createCompleteStorage(bool renderTarget) const
     // use existing storage level count, when previously specified by TexStorage*D
     GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth));
 
-    return mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels);
+    // TODO: Verify creation of the storage succeeded
+    *outStorage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels);
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
 {
     SafeDelete(mTexStorage);
     mTexStorage = newCompleteTexStorage;
@@ -1583,9 +2085,11 @@ void TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
 
     // We do not support managed 3D storage, as that is D3D9/ES2-only
     ASSERT(!mTexStorage->isManaged());
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_3D::updateStorage()
+gl::Error TextureD3D_3D::updateStorage()
 {
     ASSERT(mTexStorage != NULL);
     GLint storageLevels = mTexStorage->getLevelCount();
@@ -1593,43 +2097,15 @@ void TextureD3D_3D::updateStorage()
     {
         if (mImageArray[level]->isDirty() && isLevelComplete(level))
         {
-            updateStorageLevel(level);
-        }
-    }
-}
-
-bool TextureD3D_3D::ensureRenderTarget()
-{
-    initializeStorage(true);
-
-    if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getBaseLevelDepth() > 0)
-    {
-        ASSERT(mTexStorage);
-        if (!mTexStorage->isRenderTarget())
-        {
-            TextureStorage *newRenderTargetStorage = createCompleteStorage(true);
-
-            if (!mRenderer->copyToRenderTarget3D(newRenderTargetStorage, mTexStorage))
+            gl::Error error = updateStorageLevel(level);
+            if (error.isError())
             {
-                delete newRenderTargetStorage;
-                return gl::error(GL_OUT_OF_MEMORY, false);
+                return error;
             }
-
-            setCompleteTexStorage(newRenderTargetStorage);
         }
     }
 
-    return (mTexStorage && mTexStorage->isRenderTarget());
-}
-
-TextureStorage *TextureD3D_3D::getBaseLevelStorage()
-{
-    return mTexStorage;
-}
-
-const ImageD3D *TextureD3D_3D::getBaseLevelImage() const
-{
-    return mImageArray[0];
+    return gl::Error(GL_NO_ERROR);
 }
 
 bool TextureD3D_3D::isValidLevel(int level) const
@@ -1685,15 +2161,28 @@ bool TextureD3D_3D::isLevelComplete(int level) const
     return true;
 }
 
-void TextureD3D_3D::updateStorageLevel(int level)
+bool TextureD3D_3D::isImageComplete(const gl::ImageIndex &index) const
+{
+    return isLevelComplete(index.mipIndex);
+}
+
+gl::Error TextureD3D_3D::updateStorageLevel(int level)
 {
     ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
     ASSERT(isLevelComplete(level));
 
     if (mImageArray[level]->isDirty())
     {
-        commitRect(level, 0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
+        gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+        gl::Box region(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
+        gl::Error error = commitRegion(index, region);
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
@@ -1727,22 +2216,26 @@ void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei wi
     }
 }
 
-void TextureD3D_3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
+gl::ImageIndexIterator TextureD3D_3D::imageIterator() const
 {
-    if (isValidLevel(level))
-    {
-        ImageD3D *image = mImageArray[level];
-        if (image->copyToStorage3D(mTexStorage, level, xoffset, yoffset, zoffset, width, height, depth))
-        {
-            image->markClean();
-        }
-    }
+    return gl::ImageIndexIterator::Make3D(0, mTexStorage->getLevelCount(),
+                                          gl::ImageIndex::ENTIRE_LEVEL, gl::ImageIndex::ENTIRE_LEVEL);
+}
+
+gl::ImageIndex TextureD3D_3D::getImageIndex(GLint mip, GLint /*layer*/) const
+{
+    // The "layer" here does not apply to 3D images. We use one Image per mip.
+    return gl::ImageIndex::Make3D(mip);
 }
 
+bool TextureD3D_3D::isValidIndex(const gl::ImageIndex &index) const
+{
+    return (mTexStorage && index.type == GL_TEXTURE_3D &&
+            index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
+}
 
-TextureD3D_2DArray::TextureD3D_2DArray(Renderer *renderer)
-    : TextureD3D(renderer),
-      mTexStorage(NULL)
+TextureD3D_2DArray::TextureD3D_2DArray(RendererD3D *renderer)
+    : TextureD3D(renderer)
 {
     for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
     {
@@ -1791,11 +2284,6 @@ GLsizei TextureD3D_2DArray::getHeight(GLint level) const
     return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0;
 }
 
-GLsizei TextureD3D_2DArray::getLayers(GLint level) const
-{
-    return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mLayerCounts[level] : 0;
-}
-
 GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const
 {
     return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE;
@@ -1806,7 +2294,9 @@ bool TextureD3D_2DArray::isDepth(GLint level) const
     return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
-void TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth,
+                                       GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack,
+                                       const void *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
 
@@ -1820,11 +2310,20 @@ void TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width, GLs
     for (int i = 0; i < depth; i++)
     {
         const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
-        TextureD3D::setImage(unpack, type, layerPixels, mImageArray[level][i]);
+        gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
+        gl::Error error = TextureD3D::setImage(unpack, type, layerPixels, index);
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum format,
+                                                 GLsizei width, GLsizei height, GLsizei depth,
+                                                 GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
 
@@ -1837,11 +2336,19 @@ void TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum f
     for (int i = 0; i < depth; i++)
     {
         const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
-        TextureD3D::setCompressedImage(imageSize, layerPixels, mImageArray[level][i]);
+        gl::Error error = TextureD3D::setCompressedImage(unpack, imageSize, layerPixels, mImageArray[level][i]);
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                       GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
+                                       const gl::PixelUnpackState &unpack, const void *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
 
@@ -1854,14 +2361,20 @@ void TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset, GLi
         const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
 
         gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
-        if (TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, unpack, layerPixels, index))
+        gl::Error error = TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type,
+                                               unpack, layerPixels, index);
+        if (error.isError())
         {
-            commitRect(level, xoffset, yoffset, layer, width, height);
+            return error;
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
+gl::Error TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                                 GLsizei width, GLsizei height, GLsizei depth, GLenum format,
+                                                 GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
 
@@ -1873,52 +2386,75 @@ void TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xo
         int layer = zoffset + i;
         const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
 
-        if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, layerPixels, mImageArray[level][layer]))
+        gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, unpack, layerPixels, mImageArray[level][layer]);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
+        gl::Box region(xoffset, yoffset, 0, width, height, 1);
+        error = commitRegion(index, region);
+        if (error.isError())
         {
-            commitRect(level, xoffset, yoffset, layer, width, height);
+            return error;
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2DArray::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_2DArray::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
 {
     UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented.");
 }
 
-void TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
 {
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
 
-    // can only make our texture storage to a render target if level 0 is defined (with a width & height) and
-    // the current level we're copying to is defined (with appropriate format, width & height)
-    bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0);
+    gl::Rectangle sourceRect(x, y, width, height);
+    gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zoffset);
 
-    if (!mImageArray[level][0]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget))
+    if (canCreateRenderTargetForImage(index))
     {
-        mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, x, y, width, height, source);
+        gl::Error error = mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, sourceRect, source);
+        if (error.isError())
+        {
+            return error;
+        }
+
         mDirtyImages = true;
     }
     else
     {
-        ensureRenderTarget();
+        gl::Error error = ensureRenderTarget();
+        if (error.isError())
+        {
+            return error;
+        }
 
         if (isValidLevel(level))
         {
-            updateStorageLevel(level);
-
-            gl::Rectangle sourceRect;
-            sourceRect.x = x;
-            sourceRect.width = width;
-            sourceRect.y = y;
-            sourceRect.height = height;
+            error = updateStorageLevel(level);
+            if (error.isError())
+            {
+                return error;
+            }
 
-            mRenderer->copyImage2DArray(source, sourceRect, gl::GetInternalFormatInfo(getInternalFormat(0)).format,
-                                        xoffset, yoffset, zoffset, mTexStorage, level);
+            error = mRenderer->copyImage2DArray(source, sourceRect, gl::GetInternalFormatInfo(getInternalFormat(0)).format,
+                                                xoffset, yoffset, zoffset, mTexStorage, level);
+            if (error.isError())
+            {
+                return error;
+            }
         }
     }
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+gl::Error TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
 {
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
 
@@ -1945,11 +2481,20 @@ void TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum internalf
         }
     }
 
-    mImmutable = true;
-
+    // TODO(geofflang): Verify storage creation had no errors
     bool renderTarget = IsRenderTargetUsage(mUsage);
     TextureStorage *storage = mRenderer->createTextureStorage2DArray(internalformat, renderTarget, width, height, depth, levels);
-    setCompleteTexStorage(storage);
+
+    gl::Error error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
+    mImmutable = true;
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 void TextureD3D_2DArray::bindTexImage(egl::Surface *surface)
@@ -1963,7 +2508,7 @@ void TextureD3D_2DArray::releaseTexImage()
 }
 
 
-void TextureD3D_2DArray::generateMipmaps()
+void TextureD3D_2DArray::initMipmapsImages()
 {
     int baseWidth = getBaseLevelWidth();
     int baseHeight = getBaseLevelHeight();
@@ -1976,76 +2521,78 @@ void TextureD3D_2DArray::generateMipmaps()
     {
         redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth);
     }
-
-    if (mTexStorage && mTexStorage->isRenderTarget())
-    {
-        mTexStorage->generateMipmaps();
-
-        for (int level = 1; level < levelCount; level++)
-        {
-            for (int layer = 0; layer < mLayerCounts[level]; layer++)
-            {
-                mImageArray[level][layer]->markClean();
-            }
-        }
-    }
-    else
-    {
-        for (int level = 1; level < levelCount; level++)
-        {
-            for (int layer = 0; layer < mLayerCounts[level]; layer++)
-            {
-                mRenderer->generateMipmap(mImageArray[level][layer], mImageArray[level - 1][layer]);
-            }
-        }
-    }
 }
 
 unsigned int TextureD3D_2DArray::getRenderTargetSerial(const gl::ImageIndex &index)
 {
-    return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0);
+    return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
 }
 
-RenderTarget *TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index)
+gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
 {
     // ensure the underlying texture is created
-    if (!ensureRenderTarget())
+    gl::Error error = ensureRenderTarget();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = updateStorageLevel(index.mipIndex);
+    if (error.isError())
     {
-        return NULL;
+        return error;
     }
 
-    updateStorageLevel(index.mipIndex);
-    return mTexStorage->getRenderTarget(index);
+    return mTexStorage->getRenderTarget(index, outRT);
 }
 
-void TextureD3D_2DArray::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget)
 {
     // Only initialize the first time this texture is used as a render target or shader resource
     if (mTexStorage)
     {
-        return;
+        return gl::Error(GL_NO_ERROR);
     }
 
     // do not attempt to create storage for nonexistant data
     if (!isLevelComplete(0))
     {
-        return;
+        return gl::Error(GL_NO_ERROR);
     }
 
     bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
 
-    setCompleteTexStorage(createCompleteStorage(createRenderTarget));
+    TextureStorage *storage = NULL;
+    gl::Error error = createCompleteStorage(createRenderTarget, &storage);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = setCompleteTexStorage(storage);
+    if (error.isError())
+    {
+        SafeDelete(storage);
+        return error;
+    }
+
     ASSERT(mTexStorage);
 
     // flush image data to the storage
-    updateStorage();
+    error = updateStorage();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-TextureStorage *TextureD3D_2DArray::createCompleteStorage(bool renderTarget) const
+gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const
 {
     GLsizei width = getBaseLevelWidth();
     GLsizei height = getBaseLevelHeight();
-    GLsizei depth = getLayers(0);
+    GLsizei depth = getLayerCount(0);
     GLenum internalFormat = getBaseLevelInternalFormat();
 
     ASSERT(width > 0 && height > 0 && depth > 0);
@@ -2053,10 +2600,13 @@ TextureStorage *TextureD3D_2DArray::createCompleteStorage(bool renderTarget) con
     // use existing storage level count, when previously specified by TexStorage*D
     GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
 
-    return mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels);
+    // TODO(geofflang): Verify storage creation succeeds
+    *outStorage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels);
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
 {
     SafeDelete(mTexStorage);
     mTexStorage = newCompleteTexStorage;
@@ -2064,9 +2614,11 @@ void TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexSto
 
     // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only
     ASSERT(!mTexStorage->isManaged());
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureD3D_2DArray::updateStorage()
+gl::Error TextureD3D_2DArray::updateStorage()
 {
     ASSERT(mTexStorage != NULL);
     GLint storageLevels = mTexStorage->getLevelCount();
@@ -2074,43 +2626,15 @@ void TextureD3D_2DArray::updateStorage()
     {
         if (isLevelComplete(level))
         {
-            updateStorageLevel(level);
-        }
-    }
-}
-
-bool TextureD3D_2DArray::ensureRenderTarget()
-{
-    initializeStorage(true);
-
-    if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getLayers(0) > 0)
-    {
-        ASSERT(mTexStorage);
-        if (!mTexStorage->isRenderTarget())
-        {
-            TextureStorage *newRenderTargetStorage = createCompleteStorage(true);
-
-            if (!mRenderer->copyToRenderTarget2DArray(newRenderTargetStorage, mTexStorage))
+            gl::Error error = updateStorageLevel(level);
+            if (error.isError())
             {
-                delete newRenderTargetStorage;
-                return gl::error(GL_OUT_OF_MEMORY, false);
+                return error;
             }
-
-            setCompleteTexStorage(newRenderTargetStorage);
         }
     }
 
-    return (mTexStorage && mTexStorage->isRenderTarget());
-}
-
-const ImageD3D *TextureD3D_2DArray::getBaseLevelImage() const
-{
-    return (mLayerCounts[0] > 0 ? mImageArray[0][0] : NULL);
-}
-
-TextureStorage *TextureD3D_2DArray::getBaseLevelStorage()
-{
-    return mTexStorage;
+    return gl::Error(GL_NO_ERROR);
 }
 
 bool TextureD3D_2DArray::isValidLevel(int level) const
@@ -2129,7 +2653,7 @@ bool TextureD3D_2DArray::isLevelComplete(int level) const
 
     GLsizei width = getBaseLevelWidth();
     GLsizei height = getBaseLevelHeight();
-    GLsizei layers = getLayers(0);
+    GLsizei layers = getLayerCount(0);
 
     if (width <= 0 || height <= 0 || layers <= 0)
     {
@@ -2156,7 +2680,7 @@ bool TextureD3D_2DArray::isLevelComplete(int level) const
         return false;
     }
 
-    if (getLayers(level) != layers)
+    if (getLayerCount(level) != layers)
     {
         return false;
     }
@@ -2164,7 +2688,12 @@ bool TextureD3D_2DArray::isLevelComplete(int level) const
     return true;
 }
 
-void TextureD3D_2DArray::updateStorageLevel(int level)
+bool TextureD3D_2DArray::isImageComplete(const gl::ImageIndex &index) const
+{
+    return isLevelComplete(index.mipIndex);
+}
+
+gl::Error TextureD3D_2DArray::updateStorageLevel(int level)
 {
     ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts));
     ASSERT(isLevelComplete(level));
@@ -2174,9 +2703,17 @@ void TextureD3D_2DArray::updateStorageLevel(int level)
         ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL);
         if (mImageArray[level][layer]->isDirty())
         {
-            commitRect(level, 0, 0, layer, getWidth(level), getHeight(level));
+            gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
+            gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
+            gl::Error error = commitRegion(index, region);
+            if (error.isError())
+            {
+                return error;
+            }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 void TextureD3D_2DArray::deleteImages()
@@ -2198,7 +2735,7 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsiz
     // If there currently is a corresponding storage texture image, it has these parameters
     const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
     const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
-    const int storageDepth = getLayers(0);
+    const int storageDepth = getLayerCount(0);
     const GLenum storageFormat = getBaseLevelInternalFormat();
 
     for (int layer = 0; layer < mLayerCounts[level]; layer++)
@@ -2245,16 +2782,32 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsiz
     }
 }
 
-void TextureD3D_2DArray::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height)
+gl::ImageIndexIterator TextureD3D_2DArray::imageIterator() const
+{
+    return gl::ImageIndexIterator::Make2DArray(0, mTexStorage->getLevelCount(), mLayerCounts);
+}
+
+gl::ImageIndex TextureD3D_2DArray::getImageIndex(GLint mip, GLint layer) const
+{
+    return gl::ImageIndex::Make2DArray(mip, layer);
+}
+
+bool TextureD3D_2DArray::isValidIndex(const gl::ImageIndex &index) const
 {
-    if (isValidLevel(level) && layerTarget < getLayers(level))
+    // Check for having a storage and the right type of index
+    if (!mTexStorage || index.type != GL_TEXTURE_2D_ARRAY)
     {
-        ImageD3D *image = mImageArray[level][layerTarget];
-        if (image->copyToStorage2DArray(mTexStorage, level, xoffset, yoffset, layerTarget, width, height))
-        {
-            image->markClean();
-        }
+        return false;
+    }
+
+    // Check the mip index
+    if (index.mipIndex < 0 || index.mipIndex >= mTexStorage->getLevelCount())
+    {
+        return false;
     }
+
+    // Check the layer index
+    return (!index.hasLayer() || (index.layerIndex >= 0 && index.layerIndex < mLayerCounts[index.mipIndex]));
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h
index 41c73180de8..083a6335b9e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h
@@ -11,7 +11,7 @@
 
 #include "libGLESv2/renderer/TextureImpl.h"
 #include "libGLESv2/angletypes.h"
-#include "libGLESv2/constants.h"
+#include "libGLESv2/Constants.h"
 
 namespace gl
 {
@@ -23,19 +23,19 @@ namespace rx
 
 class Image;
 class ImageD3D;
-class Renderer;
+class RendererD3D;
 class RenderTarget;
 class TextureStorage;
 
 class TextureD3D : public TextureImpl
 {
   public:
-    TextureD3D(Renderer *renderer);
+    TextureD3D(RendererD3D *renderer);
     virtual ~TextureD3D();
 
     static TextureD3D *makeTextureD3D(TextureImpl *texture);
 
-    virtual TextureStorage *getNativeTexture();
+    TextureStorage *getNativeTexture();
 
     virtual void setUsage(GLenum usage) { mUsage = usage; }
     bool hasDirtyImages() const { return mDirtyImages; }
@@ -48,45 +48,68 @@ class TextureD3D : public TextureImpl
 
     bool isImmutable() const { return mImmutable; }
 
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0;
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0;
     virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index) = 0;
 
+    // Returns an iterator over all "Images" for this particular Texture.
+    virtual gl::ImageIndexIterator imageIterator() const = 0;
+
+    // Returns an ImageIndex for a particular "Image". 3D Textures do not have images for
+    // slices of their depth texures, so 3D textures ignore the layer parameter.
+    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const = 0;
+    virtual bool isValidIndex(const gl::ImageIndex &index) const = 0;
+
+    virtual gl::Error generateMipmaps();
+    TextureStorage *getStorage();
+    Image *getBaseLevelImage() const;
+
   protected:
-    void setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, Image *image);
-    bool subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                  GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index);
-    void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image);
-    bool subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                            GLenum format, GLsizei imageSize, const void *pixels, Image *image);
+    gl::Error setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, const gl::ImageIndex &index);
+    gl::Error subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                       GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index);
+    gl::Error setCompressedImage(const gl::PixelUnpackState &unpack, GLsizei imageSize, const void *pixels, Image *image);
+    gl::Error subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                                 GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels, Image *image);
     bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat);
-    bool fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
-                          GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget);
+    gl::Error fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
+                               GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget);
 
     GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const;
     int mipLevels() const;
+    virtual void initMipmapsImages() = 0;
+    bool isBaseImageZeroSize() const;
+    virtual bool isImageComplete(const gl::ImageIndex &index) const = 0;
 
-    Renderer *mRenderer;
+    bool canCreateRenderTargetForImage(const gl::ImageIndex &index) const;
+    virtual gl::Error ensureRenderTarget();
+
+    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);
+
+    RendererD3D *mRenderer;
 
     GLenum mUsage;
 
     bool mDirtyImages;
 
     bool mImmutable;
+    TextureStorage *mTexStorage;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureD3D);
 
-    virtual void initializeStorage(bool renderTarget) = 0;
+    virtual gl::Error initializeStorage(bool renderTarget) = 0;
 
-    virtual void updateStorage() = 0;
-    virtual TextureStorage *getBaseLevelStorage() = 0;
-    virtual const ImageD3D *getBaseLevelImage() const = 0;
+    virtual gl::Error updateStorage() = 0;
+
+    bool shouldUseSetData(const Image *image) const;
 };
 
 class TextureD3D_2D : public TextureD3D
 {
   public:
-    TextureD3D_2D(Renderer *renderer);
+    TextureD3D_2D(RendererD3D *renderer);
     virtual ~TextureD3D_2D();
 
     virtual Image *getImage(int level, int layer) const;
@@ -99,50 +122,49 @@ class TextureD3D_2D : public TextureD3D
     GLenum getActualFormat(GLint level) const;
     bool isDepth(GLint level) const;
 
-    virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
-    virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
-    virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
-    virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
-    virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
-    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
-    virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+    virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+    virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+    virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 
     virtual void bindTexImage(egl::Surface *surface);
     virtual void releaseTexImage();
 
-    virtual void generateMipmaps();
-
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
     virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index);
 
+    virtual gl::ImageIndexIterator imageIterator() const;
+    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
+    virtual bool isValidIndex(const gl::ImageIndex &index) const;
+
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureD3D_2D);
 
-    virtual void initializeStorage(bool renderTarget);
-    TextureStorage *createCompleteStorage(bool renderTarget) const;
-    void setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+    virtual gl::Error initializeStorage(bool renderTarget);
+    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const;
+    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
 
-    virtual void updateStorage();
-    bool ensureRenderTarget();
-    virtual TextureStorage *getBaseLevelStorage();
-    virtual const ImageD3D *getBaseLevelImage() const;
+    virtual gl::Error updateStorage();
+    virtual void initMipmapsImages();
 
     bool isValidLevel(int level) const;
     bool isLevelComplete(int level) const;
+    virtual bool isImageComplete(const gl::ImageIndex &index) const;
 
-    void updateStorageLevel(int level);
+    gl::Error updateStorageLevel(int level);
 
     void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height);
-    void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
 
-    TextureStorage *mTexStorage;
     ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
 };
 
 class TextureD3D_Cube : public TextureD3D
 {
   public:
-    TextureD3D_Cube(Renderer *renderer);
+    TextureD3D_Cube(RendererD3D *renderer);
     virtual ~TextureD3D_Cube();
 
     virtual Image *getImage(int level, int layer) const;
@@ -156,51 +178,49 @@ class TextureD3D_Cube : public TextureD3D
     GLenum getInternalFormat(GLint level, GLint layer) const;
     bool isDepth(GLint level, GLint layer) const;
 
-    virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
-    virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
-    virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
-    virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
-    virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
-    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
-    virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+    virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+    virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+    virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 
     virtual void bindTexImage(egl::Surface *surface);
     virtual void releaseTexImage();
 
-    virtual void generateMipmaps();
-
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
     virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index);
 
+    virtual gl::ImageIndexIterator imageIterator() const;
+    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
+    virtual bool isValidIndex(const gl::ImageIndex &index) const;
+
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureD3D_Cube);
 
-    virtual void initializeStorage(bool renderTarget);
-    TextureStorage *createCompleteStorage(bool renderTarget) const;
-    void setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+    virtual gl::Error initializeStorage(bool renderTarget);
+    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const;
+    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
 
-    virtual void updateStorage();
-    bool ensureRenderTarget();
-    virtual TextureStorage *getBaseLevelStorage();
-    virtual const ImageD3D *getBaseLevelImage() const;
+    virtual gl::Error updateStorage();
+    virtual void initMipmapsImages();
 
     bool isValidFaceLevel(int faceIndex, int level) const;
     bool isFaceLevelComplete(int faceIndex, int level) const;
     bool isCubeComplete() const;
-    void updateStorageFaceLevel(int faceIndex, int level);
+    virtual bool isImageComplete(const gl::ImageIndex &index) const;
+    gl::Error updateStorageFaceLevel(int faceIndex, int level);
 
     void redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height);
-    void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
 
     ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
-
-    TextureStorage *mTexStorage;
 };
 
 class TextureD3D_3D : public TextureD3D
 {
   public:
-    TextureD3D_3D(Renderer *renderer);
+    TextureD3D_3D(RendererD3D *renderer);
     virtual ~TextureD3D_3D();
 
     virtual Image *getImage(int level, int layer) const;
@@ -213,50 +233,48 @@ class TextureD3D_3D : public TextureD3D
     GLenum getInternalFormat(GLint level) const;
     bool isDepth(GLint level) const;
 
-    virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
-    virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
-    virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
-    virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
-    virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
-    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
-    virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+    virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+    virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+    virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 
     virtual void bindTexImage(egl::Surface *surface);
     virtual void releaseTexImage();
 
-    virtual void generateMipmaps();
-
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
     virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index);
 
+    virtual gl::ImageIndexIterator imageIterator() const;
+    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
+    virtual bool isValidIndex(const gl::ImageIndex &index) const;
+
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureD3D_3D);
 
-    virtual void initializeStorage(bool renderTarget);
-    TextureStorage *createCompleteStorage(bool renderTarget) const;
-    void setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+    virtual gl::Error initializeStorage(bool renderTarget);
+    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const;
+    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
 
-    virtual void updateStorage();
-    bool ensureRenderTarget();
-    virtual TextureStorage *getBaseLevelStorage();
-    virtual const ImageD3D *getBaseLevelImage() const;
+    virtual gl::Error updateStorage();
+    virtual void initMipmapsImages();
 
     bool isValidLevel(int level) const;
     bool isLevelComplete(int level) const;
-    void updateStorageLevel(int level);
+    virtual bool isImageComplete(const gl::ImageIndex &index) const;
+    gl::Error updateStorageLevel(int level);
 
     void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
-    void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
 
     ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
-
-    TextureStorage *mTexStorage;
 };
 
 class TextureD3D_2DArray : public TextureD3D
 {
   public:
-    TextureD3D_2DArray(Renderer *renderer);
+    TextureD3D_2DArray(RendererD3D *renderer);
     virtual ~TextureD3D_2DArray();
 
     virtual Image *getImage(int level, int layer) const;
@@ -265,45 +283,44 @@ class TextureD3D_2DArray : public TextureD3D
 
     GLsizei getWidth(GLint level) const;
     GLsizei getHeight(GLint level) const;
-    GLsizei getLayers(GLint level) const;
     GLenum getInternalFormat(GLint level) const;
     bool isDepth(GLint level) const;
 
-    virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
-    virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
-    virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
-    virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
-    virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
-    virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
-    virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+    virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
+    virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+    virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+    virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 
     virtual void bindTexImage(egl::Surface *surface);
     virtual void releaseTexImage();
 
-    virtual void generateMipmaps();
-
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
     virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index);
 
+    virtual gl::ImageIndexIterator imageIterator() const;
+    virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
+    virtual bool isValidIndex(const gl::ImageIndex &index) const;
+
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureD3D_2DArray);
 
-    virtual void initializeStorage(bool renderTarget);
-    TextureStorage *createCompleteStorage(bool renderTarget) const;
-    void setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+    virtual gl::Error initializeStorage(bool renderTarget);
+    virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const;
+    virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
 
-    virtual void updateStorage();
-    bool ensureRenderTarget();
-    virtual TextureStorage *getBaseLevelStorage();
-    virtual const ImageD3D *getBaseLevelImage() const;
+    virtual gl::Error updateStorage();
+    virtual void initMipmapsImages();
 
     bool isValidLevel(int level) const;
     bool isLevelComplete(int level) const;
-    void updateStorageLevel(int level);
+    virtual bool isImageComplete(const gl::ImageIndex &index) const;
+    gl::Error updateStorageLevel(int level);
 
     void deleteImages();
     void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
-    void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height);
 
     // 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
@@ -311,8 +328,6 @@ class TextureD3D_2DArray : public TextureD3D
     // sense for the Image class to not have to worry about layer subresource as well as mip subresources.
     GLsizei mLayerCounts[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
     ImageD3D **mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
-
-    TextureStorage *mTexStorage;
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp
index dedd266c09c..320b74b8edd 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp
@@ -8,6 +8,7 @@
 
 #include "libGLESv2/renderer/d3d/TextureStorage.h"
 #include "libGLESv2/renderer/d3d/TextureD3D.h"
+#include "libGLESv2/renderer/RenderTarget.h"
 #include "libGLESv2/renderer/Renderer.h"
 #include "libGLESv2/Renderbuffer.h"
 #include "libGLESv2/Texture.h"
@@ -18,17 +19,14 @@
 namespace rx
 {
 
-unsigned int TextureStorage::mCurrentTextureSerial = 1;
-
 TextureStorage::TextureStorage()
-    : mTextureSerial(issueTextureSerial()),
-      mFirstRenderTargetSerial(0),
+    : mFirstRenderTargetSerial(0),
       mRenderTargetSerialsLayerStride(0)
 {}
 
 void TextureStorage::initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride)
 {
-    mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(rtSerialsToReserve);
+    mFirstRenderTargetSerial = RenderTarget::issueSerials(rtSerialsToReserve);
     mRenderTargetSerialsLayerStride = rtSerialsLayerStride;
 }
 
@@ -38,14 +36,4 @@ unsigned int TextureStorage::getRenderTargetSerial(const gl::ImageIndex &index)
     return mFirstRenderTargetSerial + static_cast<unsigned int>(index.mipIndex) + layerOffset;
 }
 
-unsigned int TextureStorage::getTextureSerial() const
-{
-    return mTextureSerial;
-}
-
-unsigned int TextureStorage::issueTextureSerial()
-{
-    return mCurrentTextureSerial++;
-}
-
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h
index 9cc2c2977b2..da92be3c741 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h
@@ -9,20 +9,26 @@
 #ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
 #define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
 
+#include "libGLESv2/Error.h"
+
 #include "common/debug.h"
+#include "libGLESv2/Error.h"
 
 #include <GLES2/gl2.h>
+#include <cstdint>
 
 namespace gl
 {
 struct ImageIndex;
+struct Box;
+struct PixelUnpackState;
 }
 
 namespace rx
 {
-class Renderer;
 class SwapChain;
 class RenderTarget;
+class Image;
 
 class TextureStorage
 {
@@ -35,8 +41,12 @@ class TextureStorage
     virtual bool isManaged() const = 0;
     virtual int getLevelCount() const = 0;
 
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0;
-    virtual void generateMipmaps() = 0;
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0;
+    virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) = 0;
+
+    virtual gl::Error copyToStorage(TextureStorage *destStorage) = 0;
+    virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type,
+                              const gl::PixelUnpackState &unpack, const uint8_t *pixelData) = 0;
 
     unsigned int getRenderTargetSerial(const gl::ImageIndex &index) const;
     unsigned int getTextureSerial() const;
@@ -47,11 +57,6 @@ class TextureStorage
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureStorage);
 
-    const unsigned int mTextureSerial;
-    static unsigned int issueTextureSerial();
-
-    static unsigned int mCurrentTextureSerial;
-
     unsigned int mFirstRenderTargetSerial;
     unsigned int mRenderTargetSerialsLayerStride;
 };
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp
index 4f85eb94fa7..73f0c79e192 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp
@@ -9,7 +9,7 @@
 
 #include "libGLESv2/renderer/d3d/VertexBuffer.h"
 #include "libGLESv2/renderer/d3d/BufferD3D.h"
-#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
 #include "libGLESv2/VertexAttribute.h"
 
 #include "common/mathutil.h"
@@ -38,7 +38,7 @@ unsigned int VertexBuffer::getSerial() const
     return mSerial;
 }
 
-VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer)
+VertexBufferInterface::VertexBufferInterface(RendererD3D *renderer, bool dynamic) : mRenderer(renderer)
 {
     mDynamic = dynamic;
     mWritePosition = 0;
@@ -127,7 +127,7 @@ gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute
     mWritePosition += spaceRequired;
 
     // Align to 16-byte boundary
-    mWritePosition = rx::roundUp(mWritePosition, 16u);
+    mWritePosition = roundUp(mWritePosition, 16u);
 
     return gl::Error(GL_NO_ERROR);
 }
@@ -153,7 +153,7 @@ gl::Error VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &a
     mReservedSpace += requiredSpace;
 
     // Align to 16-byte boundary
-    mReservedSpace = rx::roundUp(mReservedSpace, 16u);
+    mReservedSpace = roundUp(mReservedSpace, 16u);
 
     return gl::Error(GL_NO_ERROR);
 }
@@ -197,7 +197,7 @@ bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &att
     return !requiresConversion && isAligned;
 }
 
-StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true)
+StreamingVertexBufferInterface::StreamingVertexBufferInterface(RendererD3D *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true)
 {
     setBufferSize(initialSize);
 }
@@ -231,7 +231,7 @@ gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size)
     return gl::Error(GL_NO_ERROR);
 }
 
-StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false)
+StaticVertexBufferInterface::StaticVertexBufferInterface(RendererD3D *renderer) : VertexBufferInterface(renderer, false)
 {
 }
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h
index fa747d9cb43..4b40818f8ef 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h
@@ -26,7 +26,7 @@ struct VertexAttribCurrentValueData;
 
 namespace rx
 {
-class Renderer;
+class RendererD3D;
 
 class VertexBuffer
 {
@@ -60,7 +60,7 @@ class VertexBuffer
 class VertexBufferInterface
 {
   public:
-    VertexBufferInterface(rx::Renderer *renderer, bool dynamic);
+    VertexBufferInterface(RendererD3D *renderer, bool dynamic);
     virtual ~VertexBufferInterface();
 
     gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances);
@@ -90,7 +90,7 @@ class VertexBufferInterface
   private:
     DISALLOW_COPY_AND_ASSIGN(VertexBufferInterface);
 
-    rx::Renderer *const mRenderer;
+    RendererD3D *const mRenderer;
 
     VertexBuffer* mVertexBuffer;
 
@@ -102,7 +102,7 @@ class VertexBufferInterface
 class StreamingVertexBufferInterface : public VertexBufferInterface
 {
   public:
-    StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize);
+    StreamingVertexBufferInterface(RendererD3D *renderer, std::size_t initialSize);
     ~StreamingVertexBufferInterface();
 
   protected:
@@ -112,7 +112,7 @@ class StreamingVertexBufferInterface : public VertexBufferInterface
 class StaticVertexBufferInterface : public VertexBufferInterface
 {
   public:
-    explicit StaticVertexBufferInterface(rx::Renderer *renderer);
+    explicit StaticVertexBufferInterface(RendererD3D *renderer);
     ~StaticVertexBufferInterface();
 
     gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp
index 7034b78eabc..8d3df31c8b1 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp
@@ -14,6 +14,7 @@
 #include "libGLESv2/Buffer.h"
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/VertexAttribute.h"
+#include "libGLESv2/State.h"
 
 namespace
 {
@@ -51,7 +52,7 @@ static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int ve
     return vertexDrawCount;
 }
 
-VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer)
+VertexDataManager::VertexDataManager(RendererD3D *renderer) : mRenderer(renderer)
 {
     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
     {
@@ -82,8 +83,8 @@ VertexDataManager::~VertexDataManager()
     }
 }
 
-gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[],
-                                               gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances)
+gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count,
+                                               TranslatedAttribute *translated, GLsizei instances)
 {
     if (!mStreamingBuffer)
     {
@@ -93,20 +94,22 @@ gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs
     // Invalidate static buffers that don't contain matching attributes
     for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
     {
-        translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1);
+        translated[attributeIndex].active = (state.getCurrentProgramBinary()->getSemanticIndex(attributeIndex) != -1);
+        const gl::VertexAttribute &curAttrib = state.getVertexAttribState(attributeIndex);
 
-        if (translated[attributeIndex].active && attribs[attributeIndex].enabled)
+        if (translated[attributeIndex].active && curAttrib.enabled)
         {
-            invalidateMatchingStaticData(attribs[attributeIndex], currentValues[attributeIndex]);
+            invalidateMatchingStaticData(curAttrib, state.getVertexAttribCurrentValue(attributeIndex));
         }
     }
 
     // Reserve the required space in the buffers
     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
     {
-        if (translated[i].active && attribs[i].enabled)
+        const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
+        if (translated[i].active && curAttrib.enabled)
         {
-            gl::Error error = reserveSpaceForAttrib(attribs[i], currentValues[i], count, instances);
+            gl::Error error = reserveSpaceForAttrib(curAttrib, state.getVertexAttribCurrentValue(i), count, instances);
             if (error.isError())
             {
                 return error;
@@ -117,12 +120,14 @@ gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs
     // Perform the vertex data translations
     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
     {
+        const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
         if (translated[i].active)
         {
-            if (attribs[i].enabled)
+            if (curAttrib.enabled)
             {
-                gl::Error error = storeAttribute(attribs[i], currentValues[i], &translated[i],
-                                                 start, count, instances);
+                gl::Error error = storeAttribute(curAttrib, state.getVertexAttribCurrentValue(i),
+                                                 &translated[i], start, count, instances);
+
                 if (error.isError())
                 {
                     return error;
@@ -135,7 +140,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs
                     mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE);
                 }
 
-                gl::Error error = storeCurrentValue(attribs[i], currentValues[i], &translated[i],
+                gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i],
                                                     &mCurrentValue[i], &mCurrentValueOffsets[i],
                                                     mCurrentValueBuffer[i]);
                 if (error.isError())
@@ -148,14 +153,15 @@ gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs
 
     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
     {
-        if (translated[i].active && attribs[i].enabled)
+        const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
+        if (translated[i].active && curAttrib.enabled)
         {
-            gl::Buffer *buffer = attribs[i].buffer.get();
+            gl::Buffer *buffer = curAttrib.buffer.get();
 
             if (buffer)
             {
                 BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation());
-                bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(attribs[i]));
+                bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(curAttrib));
             }
         }
     }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h
index 77287222464..64ef653221f 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h
@@ -16,8 +16,9 @@
 
 namespace gl
 {
-struct VertexAttribute;
 class ProgramBinary;
+class State;
+struct VertexAttribute;
 struct VertexAttribCurrentValueData;
 }
 
@@ -26,7 +27,7 @@ namespace rx
 class BufferD3D;
 class StreamingVertexBufferInterface;
 class VertexBuffer;
-class Renderer;
+class RendererD3D;
 
 struct TranslatedAttribute
 {
@@ -49,11 +50,11 @@ struct TranslatedAttribute
 class VertexDataManager
 {
   public:
-    VertexDataManager(rx::Renderer *renderer);
+    VertexDataManager(RendererD3D *renderer);
     virtual ~VertexDataManager();
 
-    gl::Error prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[],
-                                gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances);
+    gl::Error prepareVertexData(const gl::State &state, GLint start, GLsizei count,
+                                TranslatedAttribute *outAttribs, GLsizei instances);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(VertexDataManager);
@@ -80,7 +81,7 @@ class VertexDataManager
                                 size_t *cachedOffset,
                                 StreamingVertexBufferInterface *buffer);
 
-    rx::Renderer *const mRenderer;
+    RendererD3D *const mRenderer;
 
     StreamingVertexBufferInterface *mStreamingBuffer;
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
index d43e65ea78a..06aea9befe6 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
@@ -172,7 +172,7 @@ static void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &source
     *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
 }
 
-Blit11::Blit11(rx::Renderer11 *renderer)
+Blit11::Blit11(Renderer11 *renderer)
     : mRenderer(renderer), mBlitShaderMap(compareBlitParameters), mSwizzleShaderMap(compareSwizzleParameters),
       mVertexBuffer(NULL), mPointSampler(NULL), mLinearSampler(NULL), mScissorEnabledRasterizerState(NULL),
       mScissorDisabledRasterizerState(NULL), mDepthStencilState(NULL),
@@ -209,7 +209,7 @@ Blit11::Blit11(rx::Renderer11 *renderer)
     pointSamplerDesc.BorderColor[2] = 0.0f;
     pointSamplerDesc.BorderColor[3] = 0.0f;
     pointSamplerDesc.MinLOD = 0.0f;
-    pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? FLT_MAX : 0.0f;
+    pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f;
 
     result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler);
     ASSERT(SUCCEEDED(result));
@@ -228,7 +228,7 @@ Blit11::Blit11(rx::Renderer11 *renderer)
     linearSamplerDesc.BorderColor[2] = 0.0f;
     linearSamplerDesc.BorderColor[3] = 0.0f;
     linearSamplerDesc.MinLOD = 0.0f;
-    linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? FLT_MAX : 0.0f;
+    linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f;
 
     result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler);
     ASSERT(SUCCEEDED(result));
@@ -468,8 +468,7 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT
     deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0);
 
     // Unset the currently bound shader resource to avoid conflicts
-    ID3D11ShaderResourceView *const nullSRV = NULL;
-    deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
 
     // Apply render target
     mRenderer->setOneTimeRenderTarget(dest);
@@ -485,7 +484,7 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT
     deviceContext->RSSetViewports(1, &viewport);
 
     // Apply textures
-    deviceContext->PSSetShaderResources(0, 1, &source);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
 
     // Apply samplers
     deviceContext->PSSetSamplers(0, 1, &mPointSampler);
@@ -494,7 +493,7 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT
     deviceContext->Draw(drawCount, 0);
 
     // Unbind textures and render targets and vertex buffer
-    deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
 
     mRenderer->unapplyRenderTargets();
 
@@ -507,9 +506,9 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT
     return gl::Error(GL_NO_ERROR);
 }
 
-bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
-                         ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize,
-                         const gl::Rectangle *scissor, GLenum destFormat, GLenum filter)
+gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+                              ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize,
+                              const gl::Rectangle *scissor, GLenum destFormat, GLenum filter)
 {
     HRESULT result;
     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
@@ -531,7 +530,7 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source
     if (i == mBlitShaderMap.end())
     {
         UNREACHABLE();
-        return false;
+        return gl::Error(GL_OUT_OF_MEMORY, "Could not find appropriate shader for internal texture blit.");
     }
 
     const Shader& shader = i->second;
@@ -541,8 +540,7 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source
     result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
     if (FAILED(result))
     {
-        ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
-        return false;
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", result);
     }
 
     UINT stride = 0;
@@ -587,8 +585,7 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source
     deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0);
 
     // Unset the currently bound shader resource to avoid conflicts
-    ID3D11ShaderResourceView *const nullSRV = NULL;
-    deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
 
     // Apply render target
     mRenderer->setOneTimeRenderTarget(dest);
@@ -604,7 +601,7 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source
     deviceContext->RSSetViewports(1, &viewport);
 
     // Apply textures
-    deviceContext->PSSetShaderResources(0, 1, &source);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
 
     // Apply samplers
     ID3D11SamplerState *sampler = NULL;
@@ -612,7 +609,10 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source
     {
       case GL_NEAREST: sampler = mPointSampler;  break;
       case GL_LINEAR:  sampler = mLinearSampler; break;
-      default:         UNREACHABLE(); return false;
+
+      default:
+        UNREACHABLE();
+        return gl::Error(GL_OUT_OF_MEMORY, "Internal error, unknown blit filter mode.");
     }
     deviceContext->PSSetSamplers(0, 1, &sampler);
 
@@ -620,7 +620,7 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source
     deviceContext->Draw(drawCount, 0);
 
     // Unbind textures and render targets and vertex buffer
-    deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
 
     mRenderer->unapplyRenderTargets();
 
@@ -630,21 +630,21 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source
 
     mRenderer->markAllStateDirty();
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
-                         ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
-                         const gl::Rectangle *scissor)
+gl::Error Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+                              ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+                              const gl::Rectangle *scissor)
 {
     return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize,
                             dest, destSubresource, destArea, destSize,
                             scissor, true);
 }
 
-bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
-                       ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize,
-                       const gl::Rectangle *scissor)
+gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+                            ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize,
+                            const gl::Rectangle *scissor)
 {
     HRESULT result;
     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
@@ -654,8 +654,7 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr
     result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
     if (FAILED(result))
     {
-        ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
-        return false;
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", result);
     }
 
     UINT stride = 0;
@@ -700,8 +699,7 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr
     deviceContext->GSSetShader(NULL, NULL, 0);
 
     // Unset the currently bound shader resource to avoid conflicts
-    ID3D11ShaderResourceView *const nullSRV = NULL;
-    deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
 
     // Apply render target
     deviceContext->OMSetRenderTargets(0, NULL, dest);
@@ -717,7 +715,7 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr
     deviceContext->RSSetViewports(1, &viewport);
 
     // Apply textures
-    deviceContext->PSSetShaderResources(0, 1, &source);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
 
     // Apply samplers
     deviceContext->PSSetSamplers(0, 1, &mPointSampler);
@@ -726,7 +724,7 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr
     deviceContext->Draw(drawCount, 0);
 
     // Unbind textures and render targets and vertex buffer
-    deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
 
     mRenderer->unapplyRenderTargets();
 
@@ -736,21 +734,21 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr
 
     mRenderer->markAllStateDirty();
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
-                              ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
-                              const gl::Rectangle *scissor)
+gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+                                   ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+                                   const gl::Rectangle *scissor)
 {
     return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize,
                             dest, destSubresource, destArea, destSize,
                             scissor, false);
 }
 
-bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
-                              ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
-                              const gl::Rectangle *scissor, bool stencilOnly)
+gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+                                   ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+                                   const gl::Rectangle *scissor, bool stencilOnly)
 {
     ID3D11Device *device = mRenderer->getDevice();
     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
@@ -764,7 +762,7 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso
     {
         SafeRelease(sourceStaging);
         SafeRelease(destStaging);
-        return false;
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal staging textures for depth stencil blit.");
     }
 
     DXGI_FORMAT format = GetTextureFormat(source);
@@ -785,23 +783,23 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso
                dxgiFormatInfo.depthBits   % 8 == 0);
     }
 
-    D3D11_MAPPED_SUBRESOURCE sourceMapping, destMapping;
-    deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping);
-    deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping);
+    D3D11_MAPPED_SUBRESOURCE sourceMapping;
+    HRESULT result = deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping);
+    if (FAILED(result))
+    {
+        SafeRelease(sourceStaging);
+        SafeRelease(destStaging);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal source staging texture for depth stencil blit, HRESULT: 0x%X.", result);
+    }
 
-    if (!sourceMapping.pData || !destMapping.pData)
+    D3D11_MAPPED_SUBRESOURCE destMapping;
+    result = deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping);
+    if (FAILED(result))
     {
-        if (!sourceMapping.pData)
-        {
-            deviceContext->Unmap(sourceStaging, 0);
-        }
-        if (!destMapping.pData)
-        {
-            deviceContext->Unmap(destStaging, 0);
-        }
+        deviceContext->Unmap(sourceStaging, 0);
         SafeRelease(sourceStaging);
         SafeRelease(destStaging);
-        return false;
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal destination staging texture for depth stencil blit, HRESULT: 0x%X.", result);
     }
 
     gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
@@ -880,7 +878,7 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso
     SafeRelease(sourceStaging);
     SafeRelease(destStaging);
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
 bool Blit11::compareBlitParameters(const Blit11::BlitParameters &a, const Blit11::BlitParameters &b)
@@ -1001,12 +999,12 @@ void Blit11::buildShaderMap()
     add3DBlitShaderToMap(GL_RGBA_INTEGER,    true,  d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI,    "Blit11 3D I RGBA pixel shader"         ));
     add3DBlitShaderToMap(GL_BGRA_EXT,        false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D,     "Blit11 3D BGRA pixel shader"           ));
     add3DBlitShaderToMap(GL_RGB,             false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D,      "Blit11 3D RGB pixel shader"            ));
-    add3DBlitShaderToMap(GL_RG,              false, d3d11::CompilePS(device, g_PS_PassthroughRG3D,       "Blit11 3D RG pixel shader"             ));
     add3DBlitShaderToMap(GL_RGB_INTEGER,     false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI,    "Blit11 3D RGB UI pixel shader"         ));
     add3DBlitShaderToMap(GL_RGB_INTEGER,     true,  d3d11::CompilePS(device, g_PS_PassthroughRGB3DI,     "Blit11 3D RGB I pixel shader"          ));
-    add3DBlitShaderToMap(GL_RED,             false, d3d11::CompilePS(device, g_PS_PassthroughR3D,        "Blit11 3D R pixel shader"              ));
+    add3DBlitShaderToMap(GL_RG,              false, d3d11::CompilePS(device, g_PS_PassthroughRG3D,       "Blit11 3D RG pixel shader"             ));
     add3DBlitShaderToMap(GL_RG_INTEGER,      false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI,     "Blit11 3D RG UI pixel shader"          ));
     add3DBlitShaderToMap(GL_RG_INTEGER,      true,  d3d11::CompilePS(device, g_PS_PassthroughRG3DI,      "Blit11 3D RG I pixel shader"           ));
+    add3DBlitShaderToMap(GL_RED,             false, d3d11::CompilePS(device, g_PS_PassthroughR3D,        "Blit11 3D R pixel shader"              ));
     add3DBlitShaderToMap(GL_RED_INTEGER,     false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI,      "Blit11 3D R UI pixel shader"           ));
     add3DBlitShaderToMap(GL_RED_INTEGER,     true,  d3d11::CompilePS(device, g_PS_PassthroughR3DI,       "Blit11 3D R I pixel shader"            ));
     add3DBlitShaderToMap(GL_ALPHA,           false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D,     "Blit11 3D alpha pixel shader"          ));
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h
index d6a0b795f49..821fa9d0cc2 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h
@@ -19,12 +19,6 @@ namespace rx
 {
 class Renderer11;
 
-enum Filter
-{
-    Point,
-    Linear,
-};
-
 class Blit11
 {
   public:
@@ -34,24 +28,24 @@ class Blit11
     gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size,
                              GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
 
-    bool copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
-                     ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize,
-                     const gl::Rectangle *scissor, GLenum destFormat, GLenum filter);
-
-    bool copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
-                     ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
-                     const gl::Rectangle *scissor);
+    gl::Error copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+                          ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize,
+                          const gl::Rectangle *scissor, GLenum destFormat, GLenum filter);
 
-    bool copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
-                   ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize,
-                   const gl::Rectangle *scissor);
-
-    bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+    gl::Error copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
                           ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
                           const gl::Rectangle *scissor);
 
+    gl::Error copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+                        ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize,
+                        const gl::Rectangle *scissor);
+
+    gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+                               ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+                               const gl::Rectangle *scissor);
+
   private:
-    rx::Renderer11 *mRenderer;
+    Renderer11 *mRenderer;
 
     struct BlitParameters
     {
@@ -60,9 +54,9 @@ class Blit11
         bool m3DBlit;
     };
 
-    bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
-                          ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
-                          const gl::Rectangle *scissor, bool stencilOnly);
+    gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
+                               ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+                               const gl::Rectangle *scissor, bool stencilOnly);
 
     static bool compareBlitParameters(const BlitParameters &a, const BlitParameters &b);
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
index ecd4d4672b0..5aab37938f1 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
@@ -86,7 +86,7 @@ class Buffer11::BufferStorage11
 
     virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset,
                                  size_t size, size_t destOffset) = 0;
-    virtual bool resize(size_t size, bool preserveData) = 0;
+    virtual gl::Error resize(size_t size, bool preserveData) = 0;
 
     virtual void *map(size_t offset, size_t length, GLbitfield access) = 0;
     virtual void unmap() = 0;
@@ -112,17 +112,17 @@ class Buffer11::NativeBuffer11 : public Buffer11::BufferStorage11
 
     virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset,
                                  size_t size, size_t destOffset);
-    virtual bool resize(size_t size, bool preserveData);
+    virtual gl::Error resize(size_t size, bool preserveData);
 
     virtual void *map(size_t offset, size_t length, GLbitfield access);
     virtual void unmap();
 
-    bool setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset);
+    gl::Error setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset);
 
   private:
     ID3D11Buffer *mNativeBuffer;
 
-    static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize);
+    static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize);
 };
 
 // Pack storage represents internal storage for pack buffers. We implement pack buffers
@@ -135,7 +135,7 @@ class Buffer11::PackStorage11 : public Buffer11::BufferStorage11
 
     virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset,
                                  size_t size, size_t destOffset);
-    virtual bool resize(size_t size, bool preserveData);
+    virtual gl::Error resize(size_t size, bool preserveData);
 
     virtual void *map(size_t offset, size_t length, GLbitfield access);
     virtual void unmap();
@@ -144,7 +144,7 @@ class Buffer11::PackStorage11 : public Buffer11::BufferStorage11
 
   private:
 
-    void flushQueuedPackCommand();
+    gl::Error flushQueuedPackCommand();
 
     ID3D11Texture2D *mStagingTexture;
     DXGI_FORMAT mTextureFormat;
@@ -195,14 +195,14 @@ gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage)
     return error;
 }
 
-void *Buffer11::getData()
+gl::Error Buffer11::getData(const uint8_t **outData)
 {
     NativeBuffer11 *stagingBuffer = getStagingBuffer();
 
     if (!stagingBuffer)
     {
         // Out-of-memory
-        return NULL;
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get internal staging buffer.");
     }
 
     if (stagingBuffer->getDataRevision() > mResolvedDataRevision)
@@ -211,7 +211,7 @@ void *Buffer11::getData()
         {
             if (!mResolvedData.resize(stagingBuffer->getSize()))
             {
-                return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize data resolve buffer.");
             }
         }
 
@@ -221,7 +221,7 @@ void *Buffer11::getData()
         HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_READ, 0, &mappedResource);
         if (FAILED(result))
         {
-            return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer, result: 0x%X.", result);
         }
 
         memcpy(mResolvedData.data(), mappedResource.pData, stagingBuffer->getSize());
@@ -238,13 +238,14 @@ void *Buffer11::getData()
     {
         if (!mResolvedData.resize(mSize))
         {
-            return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize data resolve buffer.");
         }
     }
 
     ASSERT(mResolvedData.size() >= mSize);
 
-    return mResolvedData.data();
+    *outData = mResolvedData.data();
+    return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset)
@@ -265,15 +266,17 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset)
         if (stagingBuffer->getSize() < requiredSize)
         {
             bool preserveData = (offset > 0);
-            if (!stagingBuffer->resize(requiredSize, preserveData))
+            gl::Error error = stagingBuffer->resize(requiredSize, preserveData);
+            if (error.isError())
             {
-                return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal staging buffer.");
+                return error;
             }
         }
 
-        if (!stagingBuffer->setData(D3D11_MAP_WRITE, reinterpret_cast<const uint8_t *>(data), size, offset))
+        gl::Error error = stagingBuffer->setData(D3D11_MAP_WRITE, reinterpret_cast<const uint8_t *>(data), size, offset);
+        if (error.isError())
         {
-            return gl::Error(GL_OUT_OF_MEMORY, "Failed to set data on internal staging buffer.");
+            return error;
         }
 
         stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1);
@@ -411,7 +414,7 @@ void Buffer11::markBufferUsage()
     }
 }
 
-Renderer* Buffer11::getRenderer()
+RendererD3D* Buffer11::getRenderer()
 {
     return mRenderer;
 }
@@ -527,7 +530,7 @@ Buffer11::BufferStorage11 *Buffer11::getBufferStorage(BufferUsage usage)
     // resize buffer
     if (directBuffer->getSize() < mSize)
     {
-        if (!directBuffer->resize(mSize, true))
+        if (directBuffer->resize(mSize, true).isError())
         {
             // Out of memory error
             return NULL;
@@ -667,6 +670,9 @@ bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t s
         // Offset bounds are validated at the API layer
         ASSERT(sourceOffset + size <= destOffset + mBufferSize);
         memcpy(destPointer, sourcePointer, size);
+
+        context->Unmap(mNativeBuffer, 0);
+        source->unmap();
     }
     else
     {
@@ -689,7 +695,7 @@ bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t s
     return createBuffer;
 }
 
-bool Buffer11::NativeBuffer11::resize(size_t size, bool preserveData)
+gl::Error Buffer11::NativeBuffer11::resize(size_t size, bool preserveData)
 {
     ID3D11Device *device = mRenderer->getDevice();
     ID3D11DeviceContext *context = mRenderer->getDeviceContext();
@@ -702,7 +708,7 @@ bool Buffer11::NativeBuffer11::resize(size_t size, bool preserveData)
 
     if (FAILED(result))
     {
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.", result);
     }
 
     if (mNativeBuffer && preserveData)
@@ -727,10 +733,10 @@ bool Buffer11::NativeBuffer11::resize(size_t size, bool preserveData)
 
     mBufferSize = bufferDesc.ByteWidth;
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer,
+void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer,
                                                      BufferUsage usage, unsigned int bufferSize)
 {
     bufferDesc->ByteWidth = bufferSize;
@@ -748,7 +754,7 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren
       case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
         bufferDesc->Usage = D3D11_USAGE_DEFAULT;
         bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER;
-        if (!static_cast<Renderer11 *>(renderer)->isLevel9())
+        if (!renderer->isLevel9())
             bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT;
         bufferDesc->CPUAccessFlags = 0;
         break;
@@ -797,7 +803,7 @@ void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield acc
     return static_cast<GLubyte*>(mappedResource.pData) + offset;
 }
 
-bool Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset)
+gl::Error Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset)
 {
     ID3D11DeviceContext *context = mRenderer->getDeviceContext();
 
@@ -805,7 +811,7 @@ bool Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, s
     HRESULT result = context->Map(mNativeBuffer, 0, mapMode, 0, &mappedResource);
     if (FAILED(result))
     {
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer, result: 0x%X.", result);
     }
 
     uint8_t *offsetBufferPointer = reinterpret_cast<uint8_t *>(mappedResource.pData) + offset;
@@ -813,7 +819,7 @@ bool Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, s
 
     context->Unmap(mNativeBuffer, 0);
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Buffer11::NativeBuffer11::unmap()
@@ -847,18 +853,18 @@ bool Buffer11::PackStorage11::copyFromStorage(BufferStorage11 *source, size_t so
     return false;
 }
 
-bool Buffer11::PackStorage11::resize(size_t size, bool preserveData)
+gl::Error Buffer11::PackStorage11::resize(size_t size, bool preserveData)
 {
     if (size != mBufferSize)
     {
         if (!mMemoryBuffer.resize(size))
         {
-            return false;
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer storage.");
         }
         mBufferSize = size;
     }
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
 void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield access)
@@ -869,7 +875,12 @@ void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield acce
     //  and if D3D packs the staging texture memory identically to how we would fill
     //  the pack buffer according to the current pack state.
 
-    flushQueuedPackCommand();
+    gl::Error error = flushQueuedPackCommand();
+    if (error.isError())
+    {
+        return NULL;
+    }
+
     mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0);
 
     return mMemoryBuffer.data() + offset;
@@ -882,7 +893,12 @@ void Buffer11::PackStorage11::unmap()
 
 gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params)
 {
-    flushQueuedPackCommand();
+    gl::Error error = flushQueuedPackCommand();
+    if (error.isError())
+    {
+        return error;
+    }
+
     mQueuedPackCommand = new PackPixelsParams(params);
 
     D3D11_TEXTURE2D_DESC textureDesc;
@@ -947,15 +963,21 @@ gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT s
     return gl::Error(GL_NO_ERROR);
 }
 
-void Buffer11::PackStorage11::flushQueuedPackCommand()
+gl::Error Buffer11::PackStorage11::flushQueuedPackCommand()
 {
     ASSERT(mMemoryBuffer.size() > 0);
 
     if (mQueuedPackCommand)
     {
-        mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data());
+        gl::Error error = mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data());
         SafeDelete(mQueuedPackCommand);
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h
index 5f24fb4e2de..1c06bbf88aa 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h
@@ -47,7 +47,7 @@ typedef size_t DataRevision;
 class Buffer11 : public BufferD3D
 {
   public:
-    Buffer11(rx::Renderer11 *renderer);
+    Buffer11(Renderer11 *renderer);
     virtual ~Buffer11();
 
     static Buffer11 *makeBuffer11(BufferImpl *buffer);
@@ -60,11 +60,11 @@ class Buffer11 : public BufferD3D
     // BufferD3D implementation
     virtual size_t getSize() const { return mSize; }
     virtual bool supportsDirectBinding() const;
-    virtual Renderer* getRenderer();
+    RendererD3D *getRenderer() override;
 
     // BufferImpl implementation
     virtual gl::Error setData(const void* data, size_t size, GLenum usage);
-    virtual void *getData();
+    gl::Error getData(const uint8_t **outData) override;
     virtual gl::Error setSubData(const void* data, size_t size, size_t offset);
     virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
     virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr);
@@ -78,7 +78,7 @@ class Buffer11 : public BufferD3D
     class NativeBuffer11;
     class PackStorage11;
 
-    rx::Renderer11 *mRenderer;
+    Renderer11 *mRenderer;
     size_t mSize;
 
     BufferStorage11 *mMappedStorage;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
index 765d34fd3f7..7185a05506b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
@@ -104,7 +104,7 @@ Clear11::Clear11(Renderer11 *renderer)
     rsDesc.DepthBias = 0;
     rsDesc.DepthBiasClamp = 0.0f;
     rsDesc.SlopeScaledDepthBias = 0.0f;
-    rsDesc.DepthClipEnable = mRenderer->isLevel9();
+    rsDesc.DepthClipEnable = renderer->isLevel9();
     rsDesc.ScissorEnable = FALSE;
     rsDesc.MultisampleEnable = FALSE;
     rsDesc.AntialiasedLineEnable = FALSE;
@@ -119,7 +119,6 @@ Clear11::Clear11(Renderer11 *renderer)
         memset(&mIntClearShader, 0, sizeof(ClearShader));
         return;
     }
-
     mUintClearShader  = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT,  g_VS_ClearUint,  g_PS_ClearUint );
     mIntClearShader   = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT,  g_VS_ClearSint,  g_PS_ClearSint );
 }
@@ -154,7 +153,7 @@ Clear11::~Clear11()
     SafeRelease(mRasterizerState);
 }
 
-gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
+gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer)
 {
     // First determine if a scissored clear is needed, this will always require drawing a quad.
     //
@@ -217,10 +216,11 @@ gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::
             gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment);
             if (attachment)
             {
-                RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment);
-                if (!renderTarget)
+                RenderTarget11 *renderTarget = NULL;
+                gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget);
+                if (error.isError())
                 {
-                    return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
+                    return error;
                 }
 
                 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat());
@@ -290,10 +290,11 @@ gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::
         gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer();
         if (attachment)
         {
-            RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment);
-            if (!renderTarget)
+            RenderTarget11 *renderTarget = NULL;
+            gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget);
+            if (error.isError())
             {
-                return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null.");
+                return error;
             }
 
             const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h
index be8e187c40e..a7e8fea56af 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h
@@ -32,7 +32,7 @@ class Clear11
     ~Clear11();
 
     // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied.
-    gl::Error clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
+    gl::Error clearFramebuffer(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer);
 
   private:
     Renderer11 *mRenderer;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp
index a841b528625..f44d9340566 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp
@@ -4,67 +4,229 @@
 // found in the LICENSE file.
 //
 
-// Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl.
+// Fence11.cpp: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl.
 
 #include "libGLESv2/renderer/d3d/d3d11/Fence11.h"
 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
 #include "libGLESv2/main.h"
 
+#include "common/utilities.h"
+
 namespace rx
 {
 
-Fence11::Fence11(rx::Renderer11 *renderer)
+//
+// Template helpers for set and test operations.
+//
+
+template<class FenceClass>
+gl::Error FenceSetHelper(FenceClass *fence)
 {
-    mRenderer = renderer;
-    mQuery = NULL;
+    if (!fence->mQuery)
+    {
+        D3D11_QUERY_DESC queryDesc;
+        queryDesc.Query = D3D11_QUERY_EVENT;
+        queryDesc.MiscFlags = 0;
+
+        HRESULT result = fence->mRenderer->getDevice()->CreateQuery(&queryDesc, &fence->mQuery);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result);
+        }
+    }
+
+    fence->mRenderer->getDeviceContext()->End(fence->mQuery);
+    return gl::Error(GL_NO_ERROR);
 }
 
-Fence11::~Fence11()
+template <class FenceClass>
+gl::Error FenceTestHelper(FenceClass *fence, bool flushCommandBuffer, GLboolean *outFinished)
+{
+    ASSERT(fence->mQuery);
+
+    UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH);
+    HRESULT result = fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, NULL, 0, getDataFlags);
+
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result);
+    }
+    else if (fence->mRenderer->isDeviceLost())
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query.");
+    }
+
+    ASSERT(result == S_OK || result == S_FALSE);
+    *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
+    return gl::Error(GL_NO_ERROR);
+}
+
+//
+// FenceNV11
+//
+
+FenceNV11::FenceNV11(Renderer11 *renderer)
+    : FenceNVImpl(),
+      mRenderer(renderer),
+      mQuery(NULL)
+{
+}
+
+FenceNV11::~FenceNV11()
 {
     SafeRelease(mQuery);
 }
 
-bool Fence11::isSet() const
+gl::Error FenceNV11::set()
 {
-    return mQuery != NULL;
+    return FenceSetHelper(this);
 }
 
-void Fence11::set()
+gl::Error FenceNV11::test(bool flushCommandBuffer, GLboolean *outFinished)
 {
-    if (!mQuery)
-    {
-        D3D11_QUERY_DESC queryDesc;
-        queryDesc.Query = D3D11_QUERY_EVENT;
-        queryDesc.MiscFlags = 0;
+    return FenceTestHelper(this, flushCommandBuffer, outFinished);
+}
+
+gl::Error FenceNV11::finishFence(GLboolean *outFinished)
+{
+    ASSERT(outFinished);
 
-        if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
+    while (*outFinished != GL_TRUE)
+    {
+        gl::Error error = test(true, outFinished);
+        if (error.isError())
         {
-            return gl::error(GL_OUT_OF_MEMORY);
+            return error;
         }
+
+        Sleep(0);
     }
 
-    mRenderer->getDeviceContext()->End(mQuery);
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Fence11::test(bool flushCommandBuffer)
+//
+// FenceSync11
+//
+
+// Important note on accurate timers in Windows:
+//
+// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call
+// as timeGetTime on laptops and "jumping" during certain hardware events.
+//
+// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc"
+//   https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc
+//
+// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer
+// from buggy implementations.
+
+FenceSync11::FenceSync11(Renderer11 *renderer)
+    : FenceSyncImpl(),
+      mRenderer(renderer),
+      mQuery(NULL)
 {
-    ASSERT(mQuery);
+    LARGE_INTEGER counterFreqency = { 0 };
+    BOOL success = QueryPerformanceFrequency(&counterFreqency);
+    UNUSED_ASSERTION_VARIABLE(success);
+    ASSERT(success);
 
-    UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH);
-    HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, getDataFlags);
+    mCounterFrequency = counterFreqency.QuadPart;
+}
 
-    if (mRenderer->isDeviceLost())
+FenceSync11::~FenceSync11()
+{
+    SafeRelease(mQuery);
+}
+
+gl::Error FenceSync11::set()
+{
+    return FenceSetHelper(this);
+}
+
+gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+{
+    ASSERT(outResult);
+
+    bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0);
+
+    GLboolean result = GL_FALSE;
+    gl::Error error = FenceTestHelper(this, flushCommandBuffer, &result);
+    if (error.isError())
     {
-       return gl::error(GL_OUT_OF_MEMORY, true);
+        *outResult = GL_WAIT_FAILED;
+        return error;
     }
 
-    ASSERT(result == S_OK || result == S_FALSE);
-    return (result == S_OK);
+    if (result == GL_TRUE)
+    {
+        *outResult = GL_ALREADY_SIGNALED;
+        return gl::Error(GL_NO_ERROR);
+    }
+
+    if (timeout == 0)
+    {
+        *outResult = GL_TIMEOUT_EXPIRED;
+        return gl::Error(GL_NO_ERROR);
+    }
+
+    LARGE_INTEGER currentCounter = { 0 };
+    BOOL success = QueryPerformanceCounter(&currentCounter);
+    UNUSED_ASSERTION_VARIABLE(success);
+    ASSERT(success);
+
+    LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll);
+    LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;
+
+    while (currentCounter.QuadPart < endCounter && !result)
+    {
+        Sleep(0);
+        BOOL success = QueryPerformanceCounter(&currentCounter);
+        UNUSED_ASSERTION_VARIABLE(success);
+        ASSERT(success);
+
+        error = FenceTestHelper(this, flushCommandBuffer, &result);
+        if (error.isError())
+        {
+            *outResult = GL_WAIT_FAILED;
+            return error;
+        }
+    }
+
+    if (currentCounter.QuadPart >= endCounter)
+    {
+        *outResult = GL_TIMEOUT_EXPIRED;
+    }
+    else
+    {
+        *outResult = GL_CONDITION_SATISFIED;
+    }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Fence11::hasError() const
+gl::Error FenceSync11::serverWait(GLbitfield flags, GLuint64 timeout)
 {
-    return mRenderer->isDeviceLost();
+    // Because our API is currently designed to be called from a single thread, we don't need to do
+    // extra work for a server-side fence. GPU commands issued after the fence is created will always
+    // be processed after the fence is signaled.
+    return gl::Error(GL_NO_ERROR);
 }
 
+gl::Error FenceSync11::getStatus(GLint *outResult)
+{
+    GLboolean result = GL_FALSE;
+    gl::Error error = FenceTestHelper(this, false, &result);
+    if (error.isError())
+    {
+        // The spec does not specify any way to report errors during the status test (e.g. device lost)
+        // so we report the fence is unblocked in case of error or signaled.
+        *outResult = GL_SIGNALED;
+
+        return error;
+    }
+
+    *outResult = (result ? GL_SIGNALED : GL_UNSIGNALED);
+    return gl::Error(GL_NO_ERROR);
 }
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h
index 50c76217764..1223a53b90a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h
@@ -4,10 +4,10 @@
 // found in the LICENSE file.
 //
 
-// Fence11.h: Defines the rx::Fence11 class which implements rx::FenceImpl.
+// Fence11.h: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl.
 
-#ifndef LIBGLESV2_RENDERER_Fence11_H_
-#define LIBGLESV2_RENDERER_Fence11_H_
+#ifndef LIBGLESV2_RENDERER_FENCE11_H_
+#define LIBGLESV2_RENDERER_FENCE11_H_
 
 #include "libGLESv2/renderer/FenceImpl.h"
 
@@ -15,22 +15,46 @@ namespace rx
 {
 class Renderer11;
 
-class Fence11 : public FenceImpl
+class FenceNV11 : public FenceNVImpl
 {
   public:
-    explicit Fence11(rx::Renderer11 *renderer);
-    virtual ~Fence11();
+    explicit FenceNV11(Renderer11 *renderer);
+    virtual ~FenceNV11();
 
-    bool isSet() const;
-    void set();
-    bool test(bool flushCommandBuffer);
-    bool hasError() const;
+    gl::Error set();
+    gl::Error test(bool flushCommandBuffer, GLboolean *outFinished);
+    gl::Error finishFence(GLboolean *outFinished);
 
   private:
-    DISALLOW_COPY_AND_ASSIGN(Fence11);
+    DISALLOW_COPY_AND_ASSIGN(FenceNV11);
 
-    rx::Renderer11 *mRenderer;
+    template<class T> friend gl::Error FenceSetHelper(T *fence);
+    template<class T> friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished);
+
+    Renderer11 *mRenderer;
+    ID3D11Query *mQuery;
+};
+
+class FenceSync11 : public FenceSyncImpl
+{
+  public:
+    explicit FenceSync11(Renderer11 *renderer);
+    virtual ~FenceSync11();
+
+    gl::Error set();
+    gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult);
+    gl::Error serverWait(GLbitfield flags, GLuint64 timeout);
+    gl::Error getStatus(GLint *outResult);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(FenceSync11);
+
+    template<class T> friend gl::Error FenceSetHelper(T *fence);
+    template<class T> friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished);
+
+    Renderer11 *mRenderer;
     ID3D11Query *mQuery;
+    LONGLONG mCounterFrequency;
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
index 7536713af4d..e6f3e906833 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
@@ -9,6 +9,7 @@
 
 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
 #include "libGLESv2/renderer/d3d/d3d11/Image11.h"
+#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
 #include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h"
 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
@@ -22,15 +23,16 @@ namespace rx
 {
 
 Image11::Image11()
+    : mRenderer(NULL),
+      mDXGIFormat(DXGI_FORMAT_UNKNOWN),
+      mStagingTexture(NULL),
+      mStagingSubresource(0),
+      mRecoverFromStorage(false),
+      mAssociatedStorage(NULL),
+      mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()),
+      mRecoveredFromStorageCount(0)
+
 {
-    mStagingTexture = NULL;
-    mRenderer = NULL;
-    mDXGIFormat = DXGI_FORMAT_UNKNOWN;
-    mRecoverFromStorage = false;
-    mAssociatedStorage = NULL;
-    mAssociatedStorageLevel = 0;
-    mAssociatedStorageLayerTarget = 0;
-    mRecoveredFromStorageCount = 0;
 }
 
 Image11::~Image11()
@@ -41,11 +43,11 @@ Image11::~Image11()
 
 Image11 *Image11::makeImage11(Image *img)
 {
-    ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img));
-    return static_cast<rx::Image11*>(img);
+    ASSERT(HAS_DYNAMIC_TYPE(Image11*, img));
+    return static_cast<Image11*>(img);
 }
 
-void Image11::generateMipmap(Image11 *dest, Image11 *src)
+gl::Error Image11::generateMipmap(Image11 *dest, Image11 *src)
 {
     ASSERT(src->getDXGIFormat() == dest->getDXGIFormat());
     ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth());
@@ -55,21 +57,18 @@ void Image11::generateMipmap(Image11 *dest, Image11 *src)
     ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL);
 
     D3D11_MAPPED_SUBRESOURCE destMapped;
-    HRESULT destMapResult = dest->map(D3D11_MAP_WRITE, &destMapped);
-    if (FAILED(destMapResult))
+    gl::Error error = dest->map(D3D11_MAP_WRITE, &destMapped);
+    if (error.isError())
     {
-        ERR("Failed to map destination image for mip map generation. HRESULT:0x%X", destMapResult);
-        return;
+        return error;
     }
 
     D3D11_MAPPED_SUBRESOURCE srcMapped;
-    HRESULT srcMapResult = src->map(D3D11_MAP_READ, &srcMapped);
-    if (FAILED(srcMapResult))
+    error = src->map(D3D11_MAP_READ, &srcMapped);
+    if (error.isError())
     {
-        ERR("Failed to map source image for mip map generation. HRESULT:0x%X", srcMapResult);
-
         dest->unmap();
-        return;
+        return error;
     }
 
     const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(srcMapped.pData);
@@ -83,6 +82,8 @@ void Image11::generateMipmap(Image11 *dest, Image11 *src)
     src->unmap();
 
     dest->markDirty();
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 bool Image11::isDirty() const
@@ -99,32 +100,10 @@ bool Image11::isDirty() const
     return mDirty;
 }
 
-bool Image11::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+gl::Error Image11::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
 {
-    TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage);
-    return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height);
-}
+    TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(storage);
 
-bool Image11::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
-{
-    TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage);
-    return copyToStorageImpl(storage11, level, face, xoffset, yoffset, width, height);
-}
-
-bool Image11::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
-{
-    TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage);
-    return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height);
-}
-
-bool Image11::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height)
-{
-    TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage);
-    return copyToStorageImpl(storage11, level, arrayLayer, xoffset, yoffset, width, height);
-}
-
-bool Image11::copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
-{
     // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage multiple times,
     // then we should just keep the staging texture around to prevent the copying from impacting perf.
     // We allow the Image11 to copy its data to/from TextureStorage once.
@@ -134,23 +113,38 @@ bool Image11::copyToStorageImpl(TextureStorage11 *storage11, int level, int laye
     if (attemptToReleaseStagingTexture)
     {
         // If another image is relying on this Storage for its data, then we must let it recover its data before we overwrite it.
-        storage11->releaseAssociatedImage(level, layerTarget, this);
+        gl::Error error = storage11->releaseAssociatedImage(index, this);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    ID3D11Resource *stagingTexture = NULL;
+    unsigned int stagingSubresourceIndex = 0;
+    gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
+    if (error.isError())
+    {
+        return error;
     }
 
-    bool updateSubresourceSuccess = storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, layerTarget, xoffset, yoffset, 0, width, height, 1);
+    error = storage11->updateSubresourceLevel(stagingTexture, stagingSubresourceIndex, index, region);
+    if (error.isError())
+    {
+        return error;
+    }
 
     // Once the image data has been copied into the Storage, we can release it locally.
-    if (attemptToReleaseStagingTexture && updateSubresourceSuccess)
+    if (attemptToReleaseStagingTexture)
     {
-        storage11->associateImage(this, level, layerTarget);
+        storage11->associateImage(this, index);
         releaseStagingTexture();
         mRecoverFromStorage = true;
         mAssociatedStorage = storage11;
-        mAssociatedStorageLevel = level;
-        mAssociatedStorageLayerTarget = layerTarget;
+        mAssociatedImageIndex = index;
     }
 
-    return updateSubresourceSuccess;
+    return gl::Error(GL_NO_ERROR);
 }
 
 bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const
@@ -158,13 +152,17 @@ bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const
     return (mAssociatedStorage == textureStorage);
 }
 
-bool Image11::recoverFromAssociatedStorage()
+gl::Error Image11::recoverFromAssociatedStorage()
 {
     if (mRecoverFromStorage)
     {
-        createStagingTexture();
+        gl::Error error = createStagingTexture();
+        if (error.isError())
+        {
+            return error;
+        }
 
-        bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this);
+        bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedImageIndex, this);
 
         // This means that the cached TextureStorage has been modified after this Image11 released its copy of its data. 
         // This should not have happened. The TextureStorage should have told this Image11 to recover its data before it was overwritten.
@@ -173,17 +171,21 @@ bool Image11::recoverFromAssociatedStorage()
         if (textureStorageCorrect)
         {
             // CopySubResource from the Storage to the Staging texture
-            mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedStorageLevel, mAssociatedStorageLayerTarget, 0, 0, 0, mWidth, mHeight, mDepth);
+            gl::Box region(0, 0, 0, mWidth, mHeight, mDepth);
+            error = mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region);
+            if (error.isError())
+            {
+                return error;
+            }
+
             mRecoveredFromStorageCount += 1;
         }
 
         // Reset all the recovery parameters, even if the texture storage association is broken.
         disassociateStorage();
-
-        return textureStorageCorrect;
     }
 
-    return false;
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Image11::disassociateStorage()
@@ -191,16 +193,15 @@ void Image11::disassociateStorage()
     if (mRecoverFromStorage)
     {
         // Make the texturestorage release the Image11 too
-        mAssociatedStorage->disassociateImage(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this);
+        mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this);
 
         mRecoverFromStorage = false;
         mAssociatedStorage = NULL;
-        mAssociatedStorageLevel = 0;
-        mAssociatedStorageLayerTarget = 0;
+        mAssociatedImageIndex = gl::ImageIndex::MakeInvalid();
     }
 }
 
-bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease)
+bool Image11::redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease)
 {
     if (mWidth != width ||
         mHeight != height ||
@@ -227,7 +228,7 @@ bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat,
         mActualFormat = dxgiFormatInfo.internalFormat;
         mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
 
-        SafeRelease(mStagingTexture);
+        releaseStagingTexture();
         mDirty = (formatInfo.dataInitializerFunction != NULL);
 
         return true;
@@ -247,8 +248,8 @@ DXGI_FORMAT Image11::getDXGIFormat() const
 
 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
 // into the target pixel rectangle.
-void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                       GLint unpackAlignment, GLenum type, const void *input)
+gl::Error Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                            GLint unpackAlignment, GLenum type, const void *input)
 {
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
     GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment);
@@ -261,11 +262,10 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei widt
     LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type);
 
     D3D11_MAPPED_SUBRESOURCE mappedImage;
-    HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
-    if (FAILED(result))
+    gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
+    if (error.isError())
     {
-        ERR("Could not map image for loading.");
-        return;
+        return error;
     }
 
     uint8_t* offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch));
@@ -274,10 +274,12 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei widt
                  offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
 
     unmap();
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                                 const void *input)
+gl::Error Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                                      const void *input)
 {
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
     GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1);
@@ -295,11 +297,10 @@ void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GL
     LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE);
 
     D3D11_MAPPED_SUBRESOURCE mappedImage;
-    HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
-    if (FAILED(result))
+    gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
+    if (error.isError())
     {
-        ERR("Could not map image for loading.");
-        return;
+        return error;
     }
 
     uint8_t* offsetMappedData = reinterpret_cast<uint8_t*>(mappedImage.pData) + ((yoffset / outputBlockHeight) * mappedImage.RowPitch +
@@ -311,81 +312,130 @@ void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GL
                  offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
 
     unmap();
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source)
 {
-    gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer();
+    RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(source);
+    ASSERT(sourceRenderTarget->getTexture());
 
-    if (colorbuffer && colorbuffer->getActualFormat() == mActualFormat)
+    UINT subresourceIndex = sourceRenderTarget->getSubresourceIndex();
+    ID3D11Texture2D *sourceTexture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(sourceRenderTarget->getTexture());
+
+    if (!sourceTexture2D)
     {
-        // No conversion needed-- use copyback fastpath
-        ID3D11Texture2D *colorBufferTexture = NULL;
-        unsigned int subresourceIndex = 0;
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the ID3D11Texture2D from the source RenderTarget.");
+    }
+
+    gl::Error error = copy(xoffset, yoffset, zoffset, sourceArea, sourceTexture2D, subresourceIndex);
+
+    SafeRelease(sourceTexture2D);
+
+    return error;
+}
+
+gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source)
+{
+    TextureStorage11 *sourceStorage11 = TextureStorage11::makeTextureStorage11(source);
+
+    UINT subresourceIndex = sourceStorage11->getSubresourceIndex(sourceIndex);
+    ID3D11Resource *resource = NULL;
+    gl::Error error = sourceStorage11->getResource(&resource);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ID3D11Texture2D *sourceTexture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource);
+
+    if (!sourceTexture2D)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the ID3D11Texture2D from the source TextureStorage.");
+    }
+
+    error = copy(xoffset, yoffset, zoffset, sourceArea, sourceTexture2D, subresourceIndex);
+
+    SafeRelease(sourceTexture2D);
+
+    return error;
+}
+
+gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource)
+{
+    D3D11_TEXTURE2D_DESC textureDesc;
+    source->GetDesc(&textureDesc);
 
-        if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
+    if (textureDesc.Format == mDXGIFormat)
+    {
+        // No conversion needed-- use copyback fastpath
+        ID3D11Resource *stagingTexture = NULL;
+        unsigned int stagingSubresourceIndex = 0;
+        gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
+        if (error.isError())
         {
-            D3D11_TEXTURE2D_DESC textureDesc;
-            colorBufferTexture->GetDesc(&textureDesc);
+            return error;
+        }
 
-            ID3D11Device *device = mRenderer->getDevice();
-            ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+        ID3D11Device *device = mRenderer->getDevice();
+        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
 
-            ID3D11Texture2D* srcTex = NULL;
-            if (textureDesc.SampleDesc.Count > 1)
-            {
-                D3D11_TEXTURE2D_DESC resolveDesc;
-                resolveDesc.Width = textureDesc.Width;
-                resolveDesc.Height = textureDesc.Height;
-                resolveDesc.MipLevels = 1;
-                resolveDesc.ArraySize = 1;
-                resolveDesc.Format = textureDesc.Format;
-                resolveDesc.SampleDesc.Count = 1;
-                resolveDesc.SampleDesc.Quality = 0;
-                resolveDesc.Usage = D3D11_USAGE_DEFAULT;
-                resolveDesc.BindFlags = 0;
-                resolveDesc.CPUAccessFlags = 0;
-                resolveDesc.MiscFlags = 0;
-
-                HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex);
-                if (FAILED(result))
-                {
-                    ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
-                    return;
-                }
-
-                deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format);
-                subresourceIndex = 0;
-            }
-            else
+        UINT subresourceAfterResolve = sourceSubResource;
+
+        ID3D11Texture2D* srcTex = NULL;
+        if (textureDesc.SampleDesc.Count > 1)
+        {
+            D3D11_TEXTURE2D_DESC resolveDesc;
+            resolveDesc.Width = textureDesc.Width;
+            resolveDesc.Height = textureDesc.Height;
+            resolveDesc.MipLevels = 1;
+            resolveDesc.ArraySize = 1;
+            resolveDesc.Format = textureDesc.Format;
+            resolveDesc.SampleDesc.Count = 1;
+            resolveDesc.SampleDesc.Quality = 0;
+            resolveDesc.Usage = D3D11_USAGE_DEFAULT;
+            resolveDesc.BindFlags = 0;
+            resolveDesc.CPUAccessFlags = 0;
+            resolveDesc.MiscFlags = 0;
+
+            HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex);
+            if (FAILED(result))
             {
-                srcTex = colorBufferTexture;
-                srcTex->AddRef();
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
             }
 
-            D3D11_BOX srcBox;
-            srcBox.left = x;
-            srcBox.right = x + width;
-            srcBox.top = y;
-            srcBox.bottom = y + height;
-            srcBox.front = 0;
-            srcBox.back = 1;
+            deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, textureDesc.Format);
+            subresourceAfterResolve = 0;
+        }
+        else
+        {
+            srcTex = source;
+        }
 
-            deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, zoffset, srcTex, subresourceIndex, &srcBox);
+        D3D11_BOX srcBox;
+        srcBox.left = sourceArea.x;
+        srcBox.right = sourceArea.x + sourceArea.width;
+        srcBox.top = sourceArea.y;
+        srcBox.bottom = sourceArea.y + sourceArea.height;
+        srcBox.front = 0;
+        srcBox.back = 1;
 
+        deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, xoffset, yoffset, zoffset, srcTex, subresourceAfterResolve, &srcBox);
+
+        if (textureDesc.SampleDesc.Count > 1)
+        {
             SafeRelease(srcTex);
-            SafeRelease(colorBufferTexture);
         }
     }
     else
     {
         // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
         D3D11_MAPPED_SUBRESOURCE mappedImage;
-        HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
-        if (FAILED(result))
+        gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
+        if (error.isError())
         {
-            ERR("Failed to map texture for Image11::copy, HRESULT: 0x%X.", result);
-            return;
+            return error;
         }
 
         // determine the offset coordinate into the destination buffer
@@ -394,17 +444,32 @@ void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y
 
         const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
 
-        mRenderer->readPixels(source, x, y, width, height, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
+        error = mRenderer->readTextureData(source, sourceSubResource, sourceArea, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
 
         unmap();
+
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    mDirty = true;
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11Resource *Image11::getStagingTexture()
+gl::Error Image11::getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex)
 {
-    createStagingTexture();
+    gl::Error error = createStagingTexture();
+    if (error.isError())
+    {
+        return error;
+    }
 
-    return mStagingTexture;
+    *outStagingTexture = mStagingTexture;
+    *outSubresourceIndex = mStagingSubresource;
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Image11::releaseStagingTexture()
@@ -412,149 +477,149 @@ void Image11::releaseStagingTexture()
     SafeRelease(mStagingTexture);
 }
 
-unsigned int Image11::getStagingSubresource()
-{
-    createStagingTexture();
-
-    return mStagingSubresource;
-}
-
-void Image11::createStagingTexture()
+gl::Error Image11::createStagingTexture()
 {
     if (mStagingTexture)
     {
-        return;
+        return gl::Error(GL_NO_ERROR);
     }
 
+    ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0);
+
     const DXGI_FORMAT dxgiFormat = getDXGIFormat();
 
-    if (mWidth > 0 && mHeight > 0 && mDepth > 0)
-    {
-        ID3D11Device *device = mRenderer->getDevice();
-        HRESULT result;
+    ID3D11Device *device = mRenderer->getDevice();
+    HRESULT result;
 
-        int lodOffset = 1;
-        GLsizei width = mWidth;
-        GLsizei height = mHeight;
+    int lodOffset = 1;
+    GLsizei width = mWidth;
+    GLsizei height = mHeight;
 
-        // adjust size if needed for compressed textures
-        d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset);
+    // adjust size if needed for compressed textures
+    d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset);
 
-        if (mTarget == GL_TEXTURE_3D)
+    if (mTarget == GL_TEXTURE_3D)
+    {
+        ID3D11Texture3D *newTexture = NULL;
+
+        D3D11_TEXTURE3D_DESC desc;
+        desc.Width = width;
+        desc.Height = height;
+        desc.Depth = mDepth;
+        desc.MipLevels = lodOffset + 1;
+        desc.Format = dxgiFormat;
+        desc.Usage = D3D11_USAGE_STAGING;
+        desc.BindFlags = 0;
+        desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+        desc.MiscFlags = 0;
+
+        if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
         {
-            ID3D11Texture3D *newTexture = NULL;
-
-            D3D11_TEXTURE3D_DESC desc;
-            desc.Width = width;
-            desc.Height = height;
-            desc.Depth = mDepth;
-            desc.MipLevels = lodOffset + 1;
-            desc.Format = dxgiFormat;
-            desc.Usage = D3D11_USAGE_STAGING;
-            desc.BindFlags = 0;
-            desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
-            desc.MiscFlags = 0;
-
-            if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
-            {
-                std::vector<D3D11_SUBRESOURCE_DATA> initialData;
-                std::vector< std::vector<BYTE> > textureData;
-                d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth,
-                                                  lodOffset + 1, &initialData, &textureData);
+            std::vector<D3D11_SUBRESOURCE_DATA> initialData;
+            std::vector< std::vector<BYTE> > textureData;
+            d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth,
+                                              lodOffset + 1, &initialData, &textureData);
 
-                result = device->CreateTexture3D(&desc, initialData.data(), &newTexture);
-            }
-            else
-            {
-                result = device->CreateTexture3D(&desc, NULL, &newTexture);
-            }
-
-            if (FAILED(result))
-            {
-                ASSERT(result == E_OUTOFMEMORY);
-                ERR("Creating image failed.");
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
-
-            mStagingTexture = newTexture;
-            mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
+            result = device->CreateTexture3D(&desc, initialData.data(), &newTexture);
         }
-        else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP)
+        else
         {
-            ID3D11Texture2D *newTexture = NULL;
-
-            D3D11_TEXTURE2D_DESC desc;
-            desc.Width = width;
-            desc.Height = height;
-            desc.MipLevels = lodOffset + 1;
-            desc.ArraySize = 1;
-            desc.Format = dxgiFormat;
-            desc.SampleDesc.Count = 1;
-            desc.SampleDesc.Quality = 0;
-            desc.Usage = D3D11_USAGE_STAGING;
-            desc.BindFlags = 0;
-            desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
-            desc.MiscFlags = 0;
-
-            if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
-            {
-                std::vector<D3D11_SUBRESOURCE_DATA> initialData;
-                std::vector< std::vector<BYTE> > textureData;
-                d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1,
-                                                  lodOffset + 1, &initialData, &textureData);
+            result = device->CreateTexture3D(&desc, NULL, &newTexture);
+        }
 
-                result = device->CreateTexture2D(&desc, initialData.data(), &newTexture);
-            }
-            else
-            {
-                result = device->CreateTexture2D(&desc, NULL, &newTexture);
-            }
+        if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result);
+        }
 
-            if (FAILED(result))
-            {
-                ASSERT(result == E_OUTOFMEMORY);
-                ERR("Creating image failed.");
-                return gl::error(GL_OUT_OF_MEMORY);
-            }
+        mStagingTexture = newTexture;
+        mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
+    }
+    else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP)
+    {
+        ID3D11Texture2D *newTexture = NULL;
+
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width = width;
+        desc.Height = height;
+        desc.MipLevels = lodOffset + 1;
+        desc.ArraySize = 1;
+        desc.Format = dxgiFormat;
+        desc.SampleDesc.Count = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage = D3D11_USAGE_STAGING;
+        desc.BindFlags = 0;
+        desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+        desc.MiscFlags = 0;
+
+        if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
+        {
+            std::vector<D3D11_SUBRESOURCE_DATA> initialData;
+            std::vector< std::vector<BYTE> > textureData;
+            d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1,
+                                              lodOffset + 1, &initialData, &textureData);
 
-            mStagingTexture = newTexture;
-            mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
+            result = device->CreateTexture2D(&desc, initialData.data(), &newTexture);
         }
         else
         {
-            UNREACHABLE();
+            result = device->CreateTexture2D(&desc, NULL, &newTexture);
         }
+
+        if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result);
+        }
+
+        mStagingTexture = newTexture;
+        mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
+    }
+    else
+    {
+        UNREACHABLE();
     }
 
     mDirty = false;
+    return gl::Error(GL_NO_ERROR);
 }
 
-HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
+gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
 {
-    createStagingTexture();
-
     // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE.
-    recoverFromAssociatedStorage();
-
-    HRESULT result = E_FAIL;
+    gl::Error error = recoverFromAssociatedStorage();
+    if (error.isError())
+    {
+        return error;
+    }
 
-    if (mStagingTexture)
+    ID3D11Resource *stagingTexture = NULL;
+    unsigned int subresourceIndex = 0;
+    error = getStagingTexture(&stagingTexture, &subresourceIndex);
+    if (error.isError())
     {
-        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
-        result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map);
+        return error;
+    }
 
-        // this can fail if the device is removed (from TDR)
-        if (d3d11::isDeviceLostError(result))
-        {
-            mRenderer->notifyDeviceLost();
-        }
-        else if (SUCCEEDED(result))
-        {
-            mDirty = true;
-        }
+    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+    ASSERT(mStagingTexture);
+    HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map);
+
+    // this can fail if the device is removed (from TDR)
+    if (d3d11::isDeviceLostError(result))
+    {
+        mRenderer->notifyDeviceLost();
+    }
+    else if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result);
     }
 
-    return result;
+    mDirty = true;
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Image11::unmap()
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h
index a76a61f0363..a936e6d7b24 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h
@@ -11,6 +11,7 @@
 #define LIBGLESV2_RENDERER_IMAGE11_H_
 
 #include "libGLESv2/renderer/d3d/ImageD3D.h"
+#include "libGLESv2/ImageIndex.h"
 
 #include "common/debug.h"
 
@@ -21,7 +22,6 @@ class Framebuffer;
 
 namespace rx
 {
-class Renderer;
 class Renderer11;
 class TextureStorage11;
 
@@ -33,42 +33,41 @@ class Image11 : public ImageD3D
 
     static Image11 *makeImage11(Image *img);
 
-    static void generateMipmap(Image11 *dest, Image11 *src);
+    static gl::Error generateMipmap(Image11 *dest, Image11 *src);
 
     virtual bool isDirty() const;
 
-    virtual bool copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-    virtual bool copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-    virtual bool copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
-    virtual bool copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height);
+    virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
 
-    virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease);
+    bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) override;
 
     DXGI_FORMAT getDXGIFormat() const;
-    
-    virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                          GLint unpackAlignment, GLenum type, const void *input);
-    virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                                    const void *input);
 
-    virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+    virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                               GLint unpackAlignment, GLenum type, const void *input);
+    virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                                         const void *input);
 
-    bool recoverFromAssociatedStorage();
+    virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source);
+    virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea,
+                           const gl::ImageIndex &sourceIndex, TextureStorage *source);
+
+    gl::Error recoverFromAssociatedStorage();
     bool isAssociatedStorageValid(TextureStorage11* textureStorage) const;
     void disassociateStorage();
 
   protected:
-    HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
+    gl::Error map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
     void unmap();
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Image11);
 
-    bool copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+    gl::Error copyToStorageImpl(TextureStorage11 *storage11, const gl::ImageIndex &index, const gl::Box &region);
+    gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource);
 
-    ID3D11Resource *getStagingTexture();
-    unsigned int getStagingSubresource();
-    void createStagingTexture();
+    gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex);
+    gl::Error createStagingTexture();
     void releaseStagingTexture();
 
     Renderer11 *mRenderer;
@@ -79,8 +78,7 @@ class Image11 : public ImageD3D
 
     bool mRecoverFromStorage;
     TextureStorage11 *mAssociatedStorage;
-    int mAssociatedStorageLevel;
-    int mAssociatedStorageLayerTarget;
+    gl::ImageIndex mAssociatedImageIndex;
     unsigned int mRecoveredFromStorageCount;
 };
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h
index f7c2b38e7e6..3351df5ec13 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h
@@ -40,7 +40,7 @@ class IndexBuffer11 : public IndexBuffer
   private:
     DISALLOW_COPY_AND_ASSIGN(IndexBuffer11);
 
-    rx::Renderer11 *const mRenderer;
+    Renderer11 *const mRenderer;
 
     ID3D11Buffer *mBuffer;
     unsigned int mBufferSize;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
index d835e4fa684..ff90a6a69a1 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
@@ -12,6 +12,7 @@
 #include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
 #include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h"
 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/renderer/d3d/ProgramD3D.h"
 #include "libGLESv2/renderer/d3d/VertexDataManager.h"
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/VertexAttribute.h"
@@ -137,7 +138,16 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
     {
         gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS];
         GetInputLayout(attributes, shaderInputLayout);
-        ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutableForInputLayout(shaderInputLayout));
+        ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation());
+
+        ShaderExecutable *shader = NULL;
+        gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        ShaderExecutable *shader11 = ShaderExecutable11::makeShaderExecutable11(shader);
 
         D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS];
         for (unsigned int j = 0; j < ilKey.elementCount; ++j)
@@ -145,7 +155,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
             descs[j] = ilKey.elements[j].desc;
         }
 
-        HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout);
+        HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader11->getFunction(), shader11->getLength(), &inputLayout);
         if (FAILED(result))
         {
             return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
index a4e84f91c20..6a3d3475ee4 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
@@ -33,12 +33,38 @@ namespace rx
 
 PixelTransfer11::PixelTransfer11(Renderer11 *renderer)
     : mRenderer(renderer),
+      mResourcesLoaded(false),
       mBufferToTextureVS(NULL),
       mBufferToTextureGS(NULL),
       mParamsConstantBuffer(NULL),
       mCopyRasterizerState(NULL),
       mCopyDepthStencilState(NULL)
 {
+}
+
+PixelTransfer11::~PixelTransfer11()
+{
+    for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++)
+    {
+        SafeRelease(shaderMapIt->second);
+    }
+
+    mBufferToTexturePSMap.clear();
+
+    SafeRelease(mBufferToTextureVS);
+    SafeRelease(mBufferToTextureGS);
+    SafeRelease(mParamsConstantBuffer);
+    SafeRelease(mCopyRasterizerState);
+    SafeRelease(mCopyDepthStencilState);
+}
+
+gl::Error PixelTransfer11::loadResources()
+{
+    if (mResourcesLoaded)
+    {
+        return gl::Error(GL_NO_ERROR);
+    }
+
     HRESULT result = S_OK;
     ID3D11Device *device = mRenderer->getDevice();
 
@@ -56,6 +82,10 @@ PixelTransfer11::PixelTransfer11(Renderer11 *renderer)
 
     result = device->CreateRasterizerState(&rasterDesc, &mCopyRasterizerState);
     ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer rasterizer state, result: 0x%X.", result);
+    }
 
     D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
     depthStencilDesc.DepthEnable = true;
@@ -75,9 +105,13 @@ PixelTransfer11::PixelTransfer11(Renderer11 *renderer)
 
     result = device->CreateDepthStencilState(&depthStencilDesc, &mCopyDepthStencilState);
     ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer depth stencil state, result: 0x%X.", result);
+    }
 
     D3D11_BUFFER_DESC constantBufferDesc = { 0 };
-    constantBufferDesc.ByteWidth = rx::roundUp<UINT>(sizeof(CopyShaderParams), 32u);
+    constantBufferDesc.ByteWidth = roundUp<UINT>(sizeof(CopyShaderParams), 32u);
     constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
     constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
     constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
@@ -86,34 +120,39 @@ PixelTransfer11::PixelTransfer11(Renderer11 *renderer)
 
     result = device->CreateBuffer(&constantBufferDesc, NULL, &mParamsConstantBuffer);
     ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer constant buffer, result: 0x%X.", result);
+    }
     d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer");
 
-    StructZero(&mParamsData);
-
     // init shaders
-    if (mRenderer->isLevel9())
-        return;
-
     mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS");
-    mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
+    if (!mBufferToTextureVS)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader.");
+    }
 
-    buildShaderMap();
-}
+    if (!mRenderer->isLevel9())
+    {
+        mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
+        if (!mBufferToTextureGS)
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader.");
+        }
+    }
 
-PixelTransfer11::~PixelTransfer11()
-{
-    for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++)
+    gl::Error error = buildShaderMap();
+    if (error.isError())
     {
-        SafeRelease(shaderMapIt->second);
+        return error;
     }
 
-    mBufferToTexturePSMap.clear();
+    StructZero(&mParamsData);
 
-    SafeRelease(mBufferToTextureVS);
-    SafeRelease(mBufferToTextureGS);
-    SafeRelease(mParamsConstantBuffer);
-    SafeRelease(mCopyRasterizerState);
-    SafeRelease(mCopyDepthStencilState);
+    mResourcesLoaded = true;
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat,
@@ -138,18 +177,21 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons
     parametersOut->PositionScale[1]     = -2.0f / static_cast<float>(destSize.height);
 }
 
-bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
-                                          GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
+gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+                                               GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
 {
-    gl::Extents destSize = destRenderTarget->getExtents();
-
-    if (destArea.x   < 0 || destArea.x   + destArea.width    > destSize.width    ||
-        destArea.y   < 0 || destArea.y   + destArea.height   > destSize.height   ||
-        destArea.z   < 0 || destArea.z   + destArea.depth    > destSize.depth    )
+    gl::Error error = loadResources();
+    if (error.isError())
     {
-        return false;
+        return error;
     }
 
+    gl::Extents destSize = destRenderTarget->getExtents();
+
+    ASSERT(destArea.x >= 0 && destArea.x + destArea.width  <= destSize.width  &&
+           destArea.y >= 0 && destArea.y + destArea.height <= destSize.height &&
+           destArea.z >= 0 && destArea.z + destArea.depth  <= destSize.depth  );
+
     const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get();
 
     ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat));
@@ -177,7 +219,6 @@ bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, un
 
     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
 
-    ID3D11ShaderResourceView *nullSRV = NULL;
     ID3D11Buffer *nullBuffer = NULL;
     UINT zero = 0;
 
@@ -187,7 +228,7 @@ bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, un
     deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0);
     deviceContext->GSSetShader(geometryShader, NULL, 0);
     deviceContext->PSSetShader(pixelShader, NULL, 0);
-    deviceContext->PSSetShaderResources(0, 1, &bufferSRV);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV);
     deviceContext->IASetInputLayout(NULL);
     deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
 
@@ -220,21 +261,32 @@ bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, un
     deviceContext->Draw(numPixels, 0);
 
     // Unbind textures and render targets and vertex buffer
-    deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
     deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer);
 
     mRenderer->markAllStateDirty();
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void PixelTransfer11::buildShaderMap()
+gl::Error PixelTransfer11::buildShaderMap()
 {
     ID3D11Device *device = mRenderer->getDevice();
 
     mBufferToTexturePSMap[GL_FLOAT]        = d3d11::CompilePS(device, g_PS_BufferToTexture_4F,  "BufferToTexture RGBA ps");
     mBufferToTexturePSMap[GL_INT]          = d3d11::CompilePS(device, g_PS_BufferToTexture_4I,  "BufferToTexture RGBA-I ps");
     mBufferToTexturePSMap[GL_UNSIGNED_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4UI, "BufferToTexture RGBA-UI ps");
+
+    // Check that all the shaders were created successfully
+    for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++)
+    {
+        if (shaderMapIt->second == NULL)
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture pixel shader.");
+        }
+    }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h
index ed1a3ae1d0a..29552140bba 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h
@@ -11,6 +11,8 @@
 #ifndef LIBGLESV2_PIXELTRANSFER11_H_
 #define LIBGLESV2_PIXELTRANSFER11_H_
 
+#include "libGLESv2/Error.h"
+
 #include "common/platform.h"
 
 #include <GLES2/gl2.h>
@@ -38,15 +40,13 @@ class PixelTransfer11
     explicit PixelTransfer11(Renderer11 *renderer);
     ~PixelTransfer11();
 
-    static bool supportsBufferToTextureCopy(GLenum internalFormat);
-
     // unpack: the source buffer is stored in the unpack state, and buffer strides
     // offset: the start of the data within the unpack buffer
     // destRenderTarget: individual slice/layer of a target texture
     // destinationFormat/sourcePixelsType: determines shaders + shader parameters
     // destArea: the sub-section of destRenderTarget to copy to
-    bool copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
-                             GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
+    gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+                                  GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
 
   private:
 
@@ -65,11 +65,13 @@ class PixelTransfer11
     static void setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat,
                                              const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut);
 
-    void buildShaderMap();
+    gl::Error loadResources();
+    gl::Error buildShaderMap();
     ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const;
 
     Renderer11 *mRenderer;
 
+    bool mResourcesLoaded;
     std::map<GLenum, ID3D11PixelShader *> mBufferToTexturePSMap;
     ID3D11VertexShader *mBufferToTextureVS;
     ID3D11GeometryShader *mBufferToTextureGS;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp
index 7109be3e288..17ab1f8ab3c 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp
@@ -10,13 +10,14 @@
 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
 #include "libGLESv2/main.h"
+#include "common/utilities.h"
 
 #include <GLES2/gl2ext.h>
 
 namespace rx
 {
 
-Query11::Query11(rx::Renderer11 *renderer, GLenum type)
+Query11::Query11(Renderer11 *renderer, GLenum type)
     : QueryImpl(type),
       mResult(0),
       mQueryFinished(false),
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h
index 822f2542eec..f9ff467873e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h
@@ -18,7 +18,7 @@ class Renderer11;
 class Query11 : public QueryImpl
 {
   public:
-    Query11(rx::Renderer11 *renderer, GLenum type);
+    Query11(Renderer11 *renderer, GLenum type);
     virtual ~Query11();
 
     virtual gl::Error begin();
@@ -35,7 +35,7 @@ class Query11 : public QueryImpl
 
     bool mQueryFinished;
 
-    rx::Renderer11 *mRenderer;
+    Renderer11 *mRenderer;
     ID3D11Query *mQuery;
 };
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp
index 71b931f27ee..ab4f60bd988 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp
@@ -38,11 +38,14 @@ const unsigned int RenderStateCache::kMaxRasterizerStates = 4096;
 const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096;
 const unsigned int RenderStateCache::kMaxSamplerStates = 4096;
 
-RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0),
-                                       mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates),
-                                       mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates),
-                                       mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates),
-                                       mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates)
+RenderStateCache::RenderStateCache(Renderer11 *renderer)
+    : mRenderer(renderer),
+      mDevice(NULL),
+      mCounter(0),
+      mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates),
+      mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates),
+      mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates),
+      mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates)
 {
 }
 
@@ -89,7 +92,7 @@ gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, co
 
     bool mrt = false;
 
-    const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender();
+    const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(mRenderer->getWorkarounds());
 
     BlendStateKey key = { 0 };
     key.blendState = blendState;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h
index d5471a3061e..dfd1d84265c 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h
@@ -28,7 +28,7 @@ class Renderer11;
 class RenderStateCache
 {
   public:
-    RenderStateCache();
+    RenderStateCache(Renderer11 *renderer);
     virtual ~RenderStateCache();
 
     void initialize(ID3D11Device *device);
@@ -42,6 +42,7 @@ class RenderStateCache
   private:
     DISALLOW_COPY_AND_ASSIGN(RenderStateCache);
 
+    Renderer11 *mRenderer;
     unsigned long long mCounter;
 
     // Blend state cache
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp
index 3041f21faa6..aff34534921 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp
@@ -10,6 +10,7 @@
 #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
 #include "libGLESv2/main.h"
 
@@ -176,276 +177,228 @@ static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11Depth
     return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
 }
 
-RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource,
-                               ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth)
+RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target)
+{
+    ASSERT(HAS_DYNAMIC_TYPE(RenderTarget11*, target));
+    return static_cast<RenderTarget11*>(target);
+}
+
+void RenderTarget11::invalidate(GLint x, GLint y, GLsizei width, GLsizei height)
 {
-    mRenderer = Renderer11::makeRenderer11(renderer);
+    // Currently a no-op
+}
 
-    mTexture = resource;
+TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
+                                             GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples)
+    : mWidth(width),
+      mHeight(height),
+      mDepth(depth),
+      mInternalFormat(internalFormat),
+      mActualFormat(internalFormat),
+      mSamples(samples),
+      mSubresourceIndex(0),
+      mTexture(resource),
+      mRenderTarget(rtv),
+      mDepthStencil(NULL),
+      mShaderResource(srv)
+{
     if (mTexture)
     {
         mTexture->AddRef();
     }
 
-    mRenderTarget = rtv;
     if (mRenderTarget)
     {
         mRenderTarget->AddRef();
     }
 
-    mDepthStencil = NULL;
-
-    mShaderResource = srv;
     if (mShaderResource)
     {
         mShaderResource->AddRef();
     }
 
-    mSubresourceIndex = 0;
-
     if (mRenderTarget && mTexture)
     {
+        mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget);
+
         D3D11_RENDER_TARGET_VIEW_DESC desc;
         mRenderTarget->GetDesc(&desc);
 
-        unsigned int mipLevels, samples;
-        getTextureProperties(mTexture, &mipLevels, &samples);
-
-        mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget);
-        mWidth = width;
-        mHeight = height;
-        mDepth = depth;
-        mSamples = samples;
-
         const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format);
-        mInternalFormat = dxgiFormatInfo.internalFormat;
         mActualFormat = dxgiFormatInfo.internalFormat;
     }
 }
 
-RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource,
-                               ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth)
+TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
+                                             GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples)
+    : mWidth(width),
+      mHeight(height),
+      mDepth(depth),
+      mInternalFormat(internalFormat),
+      mActualFormat(internalFormat),
+      mSamples(samples),
+      mSubresourceIndex(0),
+      mTexture(resource),
+      mRenderTarget(NULL),
+      mDepthStencil(dsv),
+      mShaderResource(srv)
 {
-    mRenderer = Renderer11::makeRenderer11(renderer);
-
-    mTexture = resource;
     if (mTexture)
     {
         mTexture->AddRef();
     }
 
-    mRenderTarget = NULL;
-
-    mDepthStencil = dsv;
     if (mDepthStencil)
     {
         mDepthStencil->AddRef();
     }
 
-    mShaderResource = srv;
     if (mShaderResource)
     {
         mShaderResource->AddRef();
     }
 
-    mSubresourceIndex = 0;
-
     if (mDepthStencil && mTexture)
     {
+        mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil);
+
         D3D11_DEPTH_STENCIL_VIEW_DESC desc;
         mDepthStencil->GetDesc(&desc);
 
-        unsigned int mipLevels, samples;
-        getTextureProperties(mTexture, &mipLevels, &samples);
-
-        mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil);
-        mWidth = width;
-        mHeight = height;
-        mDepth = depth;
-        mSamples = samples;
-
         const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format);
-        mInternalFormat = dxgiFormatInfo.internalFormat;
         mActualFormat = dxgiFormatInfo.internalFormat;
     }
 }
 
-RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples)
+TextureRenderTarget11::~TextureRenderTarget11()
 {
-    mRenderer = Renderer11::makeRenderer11(renderer);
-    mTexture = NULL;
-    mRenderTarget = NULL;
-    mDepthStencil = NULL;
-    mShaderResource = NULL;
+    SafeRelease(mTexture);
+    SafeRelease(mRenderTarget);
+    SafeRelease(mDepthStencil);
+    SafeRelease(mShaderResource);
+}
 
-    const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat);
-    const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat);
+ID3D11Resource *TextureRenderTarget11::getTexture() const
+{
+    return mTexture;
+}
 
-    const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat);
-    GLuint supportedSamples = textureCaps.getNearestSamples(samples);
+ID3D11RenderTargetView *TextureRenderTarget11::getRenderTargetView() const
+{
+    return mRenderTarget;
+}
 
-    if (width > 0 && height > 0)
-    {
-        // Create texture resource
-        D3D11_TEXTURE2D_DESC desc;
-        desc.Width = width; 
-        desc.Height = height;
-        desc.MipLevels = 1;
-        desc.ArraySize = 1;
-        desc.Format = formatInfo.texFormat;
-        desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
-        desc.SampleDesc.Quality = 0;
-        desc.Usage = D3D11_USAGE_DEFAULT;
-        desc.CPUAccessFlags = 0;
-        desc.MiscFlags = 0;
-
-        // If a rendertarget or depthstencil format exists for this texture format,
-        // we'll flag it to allow binding that way. Shader resource views are a little
-        // more complicated.
-        bool bindRTV = false, bindDSV = false, bindSRV = false;
-        bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
-        bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
-        if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
-        {
-            // Multisample targets flagged for binding as depth stencil cannot also be
-            // flagged for binding as SRV, so make certain not to add the SRV flag for
-            // these targets.
-            bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1);
-        }
-
-        desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET   : 0) |
-                         (bindDSV ? D3D11_BIND_DEPTH_STENCIL   : 0) |
-                         (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0);
-
-        ID3D11Device *device = mRenderer->getDevice();
-        ID3D11Texture2D *texture = NULL;
-        HRESULT result = device->CreateTexture2D(&desc, NULL, &texture);
-        mTexture = texture;
-
-        if (result == E_OUTOFMEMORY)
-        {
-            gl::error(GL_OUT_OF_MEMORY);
-            return;
-        }
-        ASSERT(SUCCEEDED(result));
-
-        if (bindSRV)
-        {
-            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
-            srvDesc.Format = formatInfo.srvFormat;
-            srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
-            srvDesc.Texture2D.MostDetailedMip = 0;
-            srvDesc.Texture2D.MipLevels = 1;
-            result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource);
-
-            if (result == E_OUTOFMEMORY)
-            {
-                SafeRelease(mTexture);
-                gl::error(GL_OUT_OF_MEMORY);
-                return;
-            }
-            ASSERT(SUCCEEDED(result));
-        }
-
-        if (bindDSV)
-        {
-            D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
-            dsvDesc.Format = formatInfo.dsvFormat;
-            dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS;
-            dsvDesc.Texture2D.MipSlice = 0;
-            dsvDesc.Flags = 0;
-            result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil);
-
-            if (result == E_OUTOFMEMORY)
-            {
-                SafeRelease(mTexture);
-                SafeRelease(mShaderResource);
-                gl::error(GL_OUT_OF_MEMORY);
-                return;
-            }
-            ASSERT(SUCCEEDED(result));
-        }
-
-        if (bindRTV)
-        {
-            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-            rtvDesc.Format = formatInfo.rtvFormat;
-            rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
-            rtvDesc.Texture2D.MipSlice = 0;
-            result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget);
-
-            if (result == E_OUTOFMEMORY)
-            {
-                SafeRelease(mTexture);
-                SafeRelease(mShaderResource);
-                SafeRelease(mDepthStencil);
-                gl::error(GL_OUT_OF_MEMORY);
-                return;
-            }
-            ASSERT(SUCCEEDED(result));
-
-            if (formatInfo.dataInitializerFunction != NULL)
-            {
-                ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-
-                const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
-                context->ClearRenderTargetView(mRenderTarget, clearValues);
-            }
-        }
-    }
+ID3D11DepthStencilView *TextureRenderTarget11::getDepthStencilView() const
+{
+    return mDepthStencil;
+}
 
+ID3D11ShaderResourceView *TextureRenderTarget11::getShaderResourceView() const
+{
+    return mShaderResource;
+}
 
-    mWidth = width;
-    mHeight = height;
-    mDepth = 1;
-    mInternalFormat = internalFormat;
-    mSamples = supportedSamples;
-    mActualFormat = dxgiFormatInfo.internalFormat;
-    mSubresourceIndex = D3D11CalcSubresource(0, 0, 1);
+GLsizei TextureRenderTarget11::getWidth() const
+{
+    return mWidth;
 }
 
-RenderTarget11::~RenderTarget11()
+GLsizei TextureRenderTarget11::getHeight() const
 {
-    SafeRelease(mTexture);
-    SafeRelease(mRenderTarget);
-    SafeRelease(mDepthStencil);
-    SafeRelease(mShaderResource);
+    return mHeight;
 }
 
-RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target)
+GLsizei TextureRenderTarget11::getDepth() const
 {
-    ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget11*, target));
-    return static_cast<rx::RenderTarget11*>(target);
+    return mDepth;
 }
 
-void RenderTarget11::invalidate(GLint x, GLint y, GLsizei width, GLsizei height)
+GLenum TextureRenderTarget11::getInternalFormat() const
 {
-    // Currently a no-op
+    return mInternalFormat;
 }
 
-ID3D11Resource *RenderTarget11::getTexture() const
+GLenum TextureRenderTarget11::getActualFormat() const
 {
-    return mTexture;
+    return mActualFormat;
 }
 
-ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const
+GLsizei TextureRenderTarget11::getSamples() const
 {
-    return mRenderTarget;
+    return mSamples;
 }
 
-ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const
+unsigned int TextureRenderTarget11::getSubresourceIndex() const
 {
-    return mDepthStencil;
+    return mSubresourceIndex;
 }
 
-ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const
+
+SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, bool depth)
+    : mSwapChain(swapChain),
+      mDepth(depth)
 {
-    return mShaderResource;
+    ASSERT(mSwapChain);
 }
 
-unsigned int RenderTarget11::getSubresourceIndex() const
+SurfaceRenderTarget11::~SurfaceRenderTarget11()
 {
-    return mSubresourceIndex;
+}
+
+GLsizei SurfaceRenderTarget11::getWidth() const
+{
+    return mSwapChain->getWidth();
+}
+
+GLsizei SurfaceRenderTarget11::getHeight() const
+{
+    return mSwapChain->getHeight();
+}
+
+GLsizei SurfaceRenderTarget11::getDepth() const
+{
+    return 1;
+}
+
+GLenum SurfaceRenderTarget11::getInternalFormat() const
+{
+    return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat());
+}
+
+GLenum SurfaceRenderTarget11::getActualFormat() const
+{
+    return d3d11::GetDXGIFormatInfo(d3d11::GetTextureFormatInfo(getInternalFormat()).texFormat).internalFormat;
+}
+
+GLsizei SurfaceRenderTarget11::getSamples() const
+{
+    // Our EGL surfaces do not support multisampling.
+    return 0;
+}
+
+ID3D11Resource *SurfaceRenderTarget11::getTexture() const
+{
+    return (mDepth ? mSwapChain->getDepthStencilTexture() : mSwapChain->getOffscreenTexture());
+}
+
+ID3D11RenderTargetView *SurfaceRenderTarget11::getRenderTargetView() const
+{
+    return (mDepth ? NULL : mSwapChain->getRenderTarget());
+}
+
+ID3D11DepthStencilView *SurfaceRenderTarget11::getDepthStencilView() const
+{
+    return (mDepth ? mSwapChain->getDepthStencil() : NULL);
+}
+
+ID3D11ShaderResourceView *SurfaceRenderTarget11::getShaderResourceView() const
+{
+    return (mDepth ? mSwapChain->getDepthStencilShaderResource() : mSwapChain->getRenderTargetShaderResource());
+}
+
+unsigned int SurfaceRenderTarget11::getSubresourceIndex() const
+{
+    return 0;
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h
index 82182957afb..c7babdda3f4 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h
@@ -14,39 +14,95 @@
 
 namespace rx
 {
-class Renderer;
-class Renderer11;
+class SwapChain11;
 
 class RenderTarget11 : public RenderTarget
 {
   public:
-    // RenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them
-    RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth);
-    RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth);
-    RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples);
-    virtual ~RenderTarget11();
+    RenderTarget11() { }
+    virtual ~RenderTarget11() { }
 
     static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget);
 
-    virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height);
+    void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) override;
 
-    ID3D11Resource *getTexture() const;
-    ID3D11RenderTargetView *getRenderTargetView() const;
-    ID3D11DepthStencilView *getDepthStencilView() const;
-    ID3D11ShaderResourceView *getShaderResourceView() const;
+    virtual ID3D11Resource *getTexture() const = 0;
+    virtual ID3D11RenderTargetView *getRenderTargetView() const = 0;
+    virtual ID3D11DepthStencilView *getDepthStencilView() const = 0;
+    virtual ID3D11ShaderResourceView *getShaderResourceView() const = 0;
 
-    unsigned int getSubresourceIndex() const;
+    virtual unsigned int getSubresourceIndex() const = 0;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(RenderTarget11);
+};
+
+class TextureRenderTarget11 : public RenderTarget11
+{
+  public:
+    // TextureRenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them
+    TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
+                           GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples);
+    TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
+                           GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples);
+    virtual ~TextureRenderTarget11();
+
+    GLsizei getWidth() const override;
+    GLsizei getHeight() const override;
+    GLsizei getDepth() const override;
+    GLenum getInternalFormat() const override;
+    GLenum getActualFormat() const override;
+    GLsizei getSamples() const override;
+
+    ID3D11Resource *getTexture() const override;
+    ID3D11RenderTargetView *getRenderTargetView() const override;
+    ID3D11DepthStencilView *getDepthStencilView() const override;
+    ID3D11ShaderResourceView *getShaderResourceView() const override;
+
+    unsigned int getSubresourceIndex() const override;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(TextureRenderTarget11);
+
+    GLsizei mWidth;
+    GLsizei mHeight;
+    GLsizei mDepth;
+    GLenum mInternalFormat;
+    GLenum mActualFormat;
+    GLsizei mSamples;
 
     unsigned int mSubresourceIndex;
     ID3D11Resource *mTexture;
     ID3D11RenderTargetView *mRenderTarget;
     ID3D11DepthStencilView *mDepthStencil;
     ID3D11ShaderResourceView *mShaderResource;
+};
+
+class SurfaceRenderTarget11 : public RenderTarget11
+{
+  public:
+    SurfaceRenderTarget11(SwapChain11 *swapChain, bool depth);
+    virtual ~SurfaceRenderTarget11();
+
+    GLsizei getWidth() const override;
+    GLsizei getHeight() const override;
+    GLsizei getDepth() const override;
+    GLenum getInternalFormat() const override;
+    GLenum getActualFormat() const override;
+    GLsizei getSamples() const override;
+
+    ID3D11Resource *getTexture() const override;
+    ID3D11RenderTargetView *getRenderTargetView() const override;
+    ID3D11DepthStencilView *getDepthStencilView() const override;
+    ID3D11ShaderResourceView *getShaderResourceView() const override;
+
+    unsigned int getSubresourceIndex() const override;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(SurfaceRenderTarget11);
 
-    Renderer11 *mRenderer;
+    SwapChain11 *mSwapChain;
+    bool mDepth;
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
index b29b2ef9109..e6d7f3025b9 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
@@ -6,12 +6,12 @@
 
 // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
 
-#include "common/platform.h"
 #include "libGLESv2/main.h"
 #include "libGLESv2/Buffer.h"
 #include "libGLESv2/FramebufferAttachment.h"
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/State.h"
 #include "libGLESv2/renderer/d3d/ProgramD3D.h"
 #include "libGLESv2/renderer/d3d/ShaderD3D.h"
 #include "libGLESv2/renderer/d3d/TextureD3D.h"
@@ -36,10 +36,12 @@
 #include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h"
 #include "libGLESv2/renderer/d3d/d3d11/VertexArray11.h"
 #include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
+#include "libGLESv2/renderer/d3d/RenderbufferD3D.h"
 
 #include "libEGL/Display.h"
 
 #include "common/utilities.h"
+#include "common/tls.h"
 
 #include <EGL/eglext.h>
 
@@ -59,6 +61,9 @@
 
 namespace rx
 {
+
+namespace
+{
 static const DXGI_FORMAT RenderTargetFormats[] =
     {
         DXGI_FORMAT_B8G8R8A8_UNORM,
@@ -77,10 +82,22 @@ enum
     MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
 };
 
-Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay)
-    : Renderer(display),
+// Does *not* increment the resource ref count!!
+ID3D11Resource *GetSRVResource(ID3D11ShaderResourceView *srv)
+{
+    ID3D11Resource *resource = NULL;
+    ASSERT(srv);
+    srv->GetResource(&resource);
+    resource->Release();
+    return resource;
+}
+
+}
+
+Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes)
+    : RendererD3D(display),
       mDc(hDc),
-      mRequestedDisplay(requestedDisplay)
+      mStateCache(this)
 {
     mVertexDataManager = NULL;
     mIndexDataManager = NULL;
@@ -112,6 +129,50 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint r
     mAppliedGeometryShader = NULL;
     mCurPointGeometryShader = NULL;
     mAppliedPixelShader = NULL;
+
+    EGLint requestedMajorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
+    EGLint requestedMinorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
+
+    if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
+    {
+        if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
+        {
+            mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
+        }
+    }
+
+    if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10)
+    {
+        if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
+        {
+            mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
+        }
+        if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
+        {
+            mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
+        }
+    }
+
+#if !defined(ANGLE_ENABLE_D3D9)
+    if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9)
+    {
+        if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3)
+        {
+            mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
+        }
+        if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2)
+        {
+            mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2);
+        }
+        if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
+        {
+            mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1);
+        }
+    }
+#endif
+
+    mDriverType = (attributes.get(EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_FALSE) == EGL_TRUE) ? D3D_DRIVER_TYPE_WARP
+                                                                                             : D3D_DRIVER_TYPE_HARDWARE;
 }
 
 Renderer11::~Renderer11()
@@ -121,8 +182,8 @@ Renderer11::~Renderer11()
 
 Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
 {
-    ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer));
-    return static_cast<rx::Renderer11*>(renderer);
+    ASSERT(HAS_DYNAMIC_TYPE(Renderer11*, renderer));
+    return static_cast<Renderer11*>(renderer);
 }
 
 #ifndef __d3d11_1_h__
@@ -136,7 +197,7 @@ EGLint Renderer11::initialize()
         return EGL_NOT_INITIALIZED;
     }
 
-#if !defined(ANGLE_PLATFORM_WINRT)
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
     mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
     mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
 
@@ -157,33 +218,14 @@ EGLint Renderer11::initialize()
     }
 #endif
 
-    D3D_FEATURE_LEVEL featureLevels[] =
-    {
-        D3D_FEATURE_LEVEL_11_0,
-        D3D_FEATURE_LEVEL_10_1,
-        D3D_FEATURE_LEVEL_10_0,
-#if !defined(ANGLE_ENABLE_D3D9)
-        D3D_FEATURE_LEVEL_9_3,
-        D3D_FEATURE_LEVEL_9_2,
-        D3D_FEATURE_LEVEL_9_1,
-#endif
-    };
-
-    D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE;
-    if (mRequestedDisplay == EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE)
-    {
-        driverType = D3D_DRIVER_TYPE_WARP;
-    }
-
     HRESULT result = S_OK;
-
 #ifdef _DEBUG
     result = D3D11CreateDevice(NULL,
-                               driverType,
+                               mDriverType,
                                NULL,
                                D3D11_CREATE_DEVICE_DEBUG,
-                               featureLevels,
-                               ArraySize(featureLevels),
+                               mAvailableFeatureLevels.data(),
+                               mAvailableFeatureLevels.size(),
                                D3D11_SDK_VERSION,
                                &mDevice,
                                &mFeatureLevel,
@@ -198,11 +240,11 @@ EGLint Renderer11::initialize()
 #endif
     {
         result = D3D11CreateDevice(NULL,
-                                   driverType,
+                                   mDriverType,
                                    NULL,
                                    0,
-                                   featureLevels,
-                                   ArraySize(featureLevels),
+                                   mAvailableFeatureLevels.data(),
+                                   mAvailableFeatureLevels.size(),
                                    D3D11_SDK_VERSION,
                                    &mDevice,
                                    &mFeatureLevel,
@@ -215,7 +257,18 @@ EGLint Renderer11::initialize()
         }
     }
 
-#if !ANGLE_SKIP_DXGI_1_2_CHECK && !defined(ANGLE_PLATFORM_WINRT)
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+    static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
+    if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
+    {
+        ID3D10Multithread *multithread;
+        result = mDevice->QueryInterface(IID_PPV_ARGS(&multithread));
+        ASSERT(SUCCEEDED(result));
+        result = multithread->SetMultithreadProtected(true);
+        ASSERT(SUCCEEDED(result));
+        multithread->Release();
+    }
+#if !ANGLE_SKIP_DXGI_1_2_CHECK
     // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required.
     // The easiest way to check is to query for a IDXGIDevice2.
     bool requireDXGI1_2 = false;
@@ -243,14 +296,11 @@ EGLint Renderer11::initialize()
         }
         SafeRelease(dxgiDevice2);
     }
+#endif
 #endif
 
-#if !defined(ANGLE_PLATFORM_WINRT)
     IDXGIDevice *dxgiDevice = NULL;
-#else
-    IDXGIDevice1 *dxgiDevice = NULL;
-#endif
-    result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice));
+    result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
 
     if (FAILED(result))
     {
@@ -281,9 +331,9 @@ EGLint Renderer11::initialize()
     }
 
     // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
-#if !defined(__MINGW32__) && defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
+#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
     ID3D11InfoQueue *infoQueue;
-    result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue),  (void **)&infoQueue);
+    result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue);
 
     if (SUCCEEDED(result))
     {
@@ -301,19 +351,6 @@ EGLint Renderer11::initialize()
     }
 #endif
 
-#if !defined(ANGLE_PLATFORM_WINRT)
-    static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
-    if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
-    {
-        ID3D10Multithread *multithread;
-        result = mDevice->QueryInterface(IID_PPV_ARGS(&multithread));
-        ASSERT(SUCCEEDED(result));
-        result = multithread->SetMultithreadProtected(true);
-        ASSERT(SUCCEEDED(result));
-        multithread->Release();
-    }
-#endif
-
     initializeDevice();
 
     return EGL_SUCCESS;
@@ -394,7 +431,7 @@ void Renderer11::deleteConfigs(ConfigDesc *configDescList)
     delete [] (configDescList);
 }
 
-void Renderer11::sync(bool block)
+gl::Error Renderer11::sync(bool block)
 {
     if (block)
     {
@@ -408,6 +445,10 @@ void Renderer11::sync(bool block)
 
             result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
             ASSERT(SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result);
+            }
         }
 
         mDeviceContext->End(mSyncQuery);
@@ -416,13 +457,17 @@ void Renderer11::sync(bool block)
         do
         {
             result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+            }
 
             // Keep polling, but allow other threads to do something useful first
             Sleep(0);
 
             if (testDeviceLost(true))
             {
-                return;
+                return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync.");
             }
         }
         while (result == S_FALSE);
@@ -431,22 +476,26 @@ void Renderer11::sync(bool block)
     {
         mDeviceContext->Flush();
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChain *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
 {
-    return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat);
+    return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
 }
 
 gl::Error Renderer11::generateSwizzle(gl::Texture *texture)
 {
     if (texture)
     {
-        TextureStorage *texStorage = texture->getNativeTexture();
+        TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+        ASSERT(textureD3D);
+
+        TextureStorage *texStorage = textureD3D->getNativeTexture();
         if (texStorage)
         {
             TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage);
-
             gl::Error error = storage11->generateSwizzles(texture->getSamplerState().swizzleRed,
                                                           texture->getSamplerState().swizzleGreen,
                                                           texture->getSamplerState().swizzleBlue,
@@ -461,16 +510,21 @@ gl::Error Renderer11::generateSwizzle(gl::Texture *texture)
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
+gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerStateParam)
 {
+    // Make sure to add the level offset for our tiny compressed texture workaround
+    TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+    gl::SamplerState samplerStateInternal = samplerStateParam;
+    samplerStateInternal.baseLevel += textureD3D->getNativeTexture()->getTopLevel();
+
     if (type == gl::SAMPLER_PIXEL)
     {
         ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits);
 
-        if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+        if (mForceSetPixelSamplerStates[index] || memcmp(&samplerStateInternal, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
         {
             ID3D11SamplerState *dxSamplerState = NULL;
-            gl::Error error = mStateCache.getSamplerState(samplerState, &dxSamplerState);
+            gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState);
             if (error.isError())
             {
                 return error;
@@ -479,7 +533,7 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, const gl:
             ASSERT(dxSamplerState != NULL);
             mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
 
-            mCurPixelSamplerStates[index] = samplerState;
+            mCurPixelSamplerStates[index] = samplerStateInternal;
         }
 
         mForceSetPixelSamplerStates[index] = false;
@@ -488,10 +542,10 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, const gl:
     {
         ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits);
 
-        if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+        if (mForceSetVertexSamplerStates[index] || memcmp(&samplerStateInternal, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
         {
             ID3D11SamplerState *dxSamplerState = NULL;
-            gl::Error error = mStateCache.getSamplerState(samplerState, &dxSamplerState);
+            gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState);
             if (error.isError())
             {
                 return error;
@@ -500,7 +554,7 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, const gl:
             ASSERT(dxSamplerState != NULL);
             mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
 
-            mCurVertexSamplerStates[index] = samplerState;
+            mCurVertexSamplerStates[index] = samplerStateInternal;
         }
 
         mForceSetVertexSamplerStates[index] = false;
@@ -513,50 +567,36 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, const gl:
 gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
 {
     ID3D11ShaderResourceView *textureSRV = NULL;
-    bool forceSetTexture = false;
 
     if (texture)
     {
-        TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation());
+        TextureD3D *textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation());
         TextureStorage *texStorage = textureImpl->getNativeTexture();
         ASSERT(texStorage != NULL);
 
         TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage);
-        gl::SamplerState samplerState;
-        texture->getSamplerStateWithNativeOffset(&samplerState);
-        textureSRV = storage11->getSRV(samplerState);
+
+        // Make sure to add the level offset for our tiny compressed texture workaround
+        gl::SamplerState samplerState = texture->getSamplerState();
+        samplerState.baseLevel += storage11->getTopLevel();
+
+        gl::Error error = storage11->getSRV(samplerState, &textureSRV);
+        if (error.isError())
+        {
+            return error;
+        }
 
         // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly
         // missing the shader resource view
         ASSERT(textureSRV != NULL);
 
-        forceSetTexture = textureImpl->hasDirtyImages();
         textureImpl->resetDirty();
     }
 
-    if (type == gl::SAMPLER_PIXEL)
-    {
-        ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits);
-
-        if (forceSetTexture || mCurPixelSRVs[index] != textureSRV)
-        {
-            mDeviceContext->PSSetShaderResources(index, 1, &textureSRV);
-        }
-
-        mCurPixelSRVs[index] = textureSRV;
-    }
-    else if (type == gl::SAMPLER_VERTEX)
-    {
-        ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits);
-
-        if (forceSetTexture || mCurVertexSRVs[index] != textureSRV)
-        {
-            mDeviceContext->VSSetShaderResources(index, 1, &textureSRV);
-        }
+    ASSERT((type == gl::SAMPLER_PIXEL && static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits) ||
+           (type == gl::SAMPLER_VERTEX && static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits));
 
-        mCurVertexSRVs[index] = textureSRV;
-    }
-    else UNREACHABLE();
+    setShaderResource(type, index, textureSRV);
 
     return gl::Error(GL_NO_ERROR);
 }
@@ -631,7 +671,7 @@ gl::Error Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
+gl::Error Renderer11::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
                                     unsigned int sampleMask)
 {
     if (mForceSetBlendState ||
@@ -831,7 +871,22 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
     return count >= minCount;
 }
 
-gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
+void Renderer11::unsetSRVsWithResource(gl::SamplerType samplerType, const ID3D11Resource *resource)
+{
+    std::vector<ID3D11ShaderResourceView *> &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+
+    for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex)
+    {
+        ID3D11ShaderResourceView *srv = currentSRVs[resourceIndex];
+
+        if (srv && GetSRVResource(srv) == resource)
+        {
+            setShaderResource(samplerType, static_cast<UINT>(resourceIndex), NULL);
+        }
+    }
+}
+
+gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
 {
     // Get the color render buffer and serial
     // Also extract the render target dimensions and view
@@ -842,7 +897,7 @@ gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
     ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
     bool missingColorRenderTarget = true;
 
-    const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender();
+    const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(getWorkarounds());
 
     for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
     {
@@ -863,17 +918,16 @@ gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
             renderTargetSerials[colorAttachment] = GetAttachmentSerial(colorbuffer);
 
             // Extract the render target dimensions and view
-            RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
-            if (!renderTarget)
+            RenderTarget11 *renderTarget = NULL;
+            gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget);
+            if (error.isError())
             {
-                return gl::Error(GL_OUT_OF_MEMORY, "Internal render target pointer unexpectedly null.");
+                return error;
             }
+            ASSERT(renderTarget);
 
             framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
-            if (!framebufferRTVs[colorAttachment])
-            {
-                return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
-            }
+            ASSERT(framebufferRTVs[colorAttachment]);
 
             if (missingColorRenderTarget)
             {
@@ -883,8 +937,12 @@ gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
                 missingColorRenderTarget = false;
             }
 
-            // TODO: Detect if this color buffer is already bound as a texture and unbind it first to prevent
-            //       D3D11 warnings.
+#if !defined(NDEBUG)
+            // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
+            ID3D11Resource *renderTargetResource = renderTarget->getTexture();
+            unsetSRVsWithResource(gl::SAMPLER_VERTEX, renderTargetResource);
+            unsetSRVsWithResource(gl::SAMPLER_PIXEL, renderTargetResource);
+#endif
         }
     }
 
@@ -905,19 +963,17 @@ gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
     ID3D11DepthStencilView* framebufferDSV = NULL;
     if (depthStencil)
     {
-        RenderTarget11 *depthStencilRenderTarget = d3d11::GetAttachmentRenderTarget(depthStencil);
-        if (!depthStencilRenderTarget)
+        RenderTarget11 *depthStencilRenderTarget = NULL;
+        gl::Error error = d3d11::GetAttachmentRenderTarget(depthStencil, &depthStencilRenderTarget);
+        if (error.isError())
         {
             SafeRelease(framebufferRTVs);
-            return gl::Error(GL_OUT_OF_MEMORY, "Internal render target pointer unexpectedly null.");
+            return error;
         }
+        ASSERT(depthStencilRenderTarget);
 
         framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
-        if (!framebufferDSV)
-        {
-            SafeRelease(framebufferRTVs);
-            return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null.");
-        }
+        ASSERT(framebufferDSV);
 
         // If there is no render buffer, the width, height and format values come from
         // the depth stencil
@@ -964,17 +1020,16 @@ gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[],
-                                        GLint first, GLsizei count, GLsizei instances)
+gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances)
 {
     TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
-    gl::Error error = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances);
+    gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances);
     if (error.isError())
     {
         return error;
     }
 
-    return mInputLayoutCache.applyVertexBuffers(attributes, programBinary);
+    return mInputLayoutCache.applyVertexBuffers(attributes, state.getCurrentProgramBinary());
 }
 
 gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
@@ -1011,28 +1066,25 @@ gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elemen
     return gl::Error(GL_NO_ERROR);
 }
 
-void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[])
+void Renderer11::applyTransformFeedbackBuffers(const gl::State& state)
 {
-    ID3D11Buffer* d3dBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
-    UINT d3dOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
+    size_t numXFBBindings = state.getTransformFeedbackBufferIndexRange();
+    ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
+
     bool requiresUpdate = false;
-    for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
+    for (size_t i = 0; i < numXFBBindings; i++)
     {
-        if (transformFeedbackBuffers[i])
+        gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i);
+        GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i);
+        ID3D11Buffer *d3dBuffer = NULL;
+        if (curXFBBuffer)
         {
-            Buffer11 *storage = Buffer11::makeBuffer11(transformFeedbackBuffers[i]->getImplementation());
-            ID3D11Buffer *buffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
-
-            d3dBuffers[i] = buffer;
-            d3dOffsets[i] = (mAppliedTFBuffers[i] != buffer) ? static_cast<UINT>(offsets[i]) : -1;
-        }
-        else
-        {
-            d3dBuffers[i] = NULL;
-            d3dOffsets[i] = 0;
+            Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation());
+            d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
         }
 
-        if (d3dBuffers[i] != mAppliedTFBuffers[i] || offsets[i] != mAppliedTFOffsets[i])
+        // TODO: mAppliedTFBuffers and friends should also be kept in a vector.
+        if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i])
         {
             requiresUpdate = true;
         }
@@ -1040,12 +1092,29 @@ void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuff
 
     if (requiresUpdate)
     {
-        mDeviceContext->SOSetTargets(ArraySize(d3dBuffers), d3dBuffers, d3dOffsets);
-        for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
+        for (size_t i = 0; i < numXFBBindings; ++i)
         {
-            mAppliedTFBuffers[i] = d3dBuffers[i];
-            mAppliedTFOffsets[i] = offsets[i];
+            gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i);
+            GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i);
+
+            if (curXFBBuffer)
+            {
+                Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation());
+                ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
+
+                mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer && mAppliedTFOffsets[i] != curXFBOffset) ?
+                                        static_cast<UINT>(curXFBOffset) : -1;
+                mAppliedTFBuffers[i] = d3dBuffer;
+            }
+            else
+            {
+                mAppliedTFBuffers[i] = NULL;
+                mCurrentD3DOffsets[i] = 0;
+            }
+            mAppliedTFOffsets[i] = curXFBOffset;
         }
+
+        mDeviceContext->SOSetTargets(numXFBBindings, mAppliedTFBuffers, mCurrentD3DOffsets);
     }
 }
 
@@ -1129,7 +1198,6 @@ gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, cons
         return gl::Error(GL_NO_ERROR);
     }
 }
-
 template<typename T>
 static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data)
 {
@@ -1213,10 +1281,17 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
     // Get the raw indices for an indexed draw
     if (type != GL_NONE && elementArrayBuffer)
     {
-        gl::Buffer *indexBuffer = elementArrayBuffer;
-        BufferImpl *storage = indexBuffer->getImplementation();
+        BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer);
         intptr_t offset = reinterpret_cast<intptr_t>(indices);
-        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+
+        const uint8_t *bufferData = NULL;
+        gl::Error error = storage->getData(&bufferData);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        indices = bufferData + offset;
     }
 
     // TODO: some level 9 hardware supports 32-bit indices; test and store support instead
@@ -1291,10 +1366,17 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
     // Get the raw indices for an indexed draw
     if (type != GL_NONE && elementArrayBuffer)
     {
-        gl::Buffer *indexBuffer = elementArrayBuffer;
-        BufferImpl *storage = indexBuffer->getImplementation();
+        BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer);
         intptr_t offset = reinterpret_cast<intptr_t>(indices);
-        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+
+        const uint8_t *bufferData = NULL;
+        gl::Error error = storage->getData(&bufferData);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        indices = bufferData + offset;
     }
 
     const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
@@ -1376,9 +1458,23 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
 gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
                                    bool rasterizerDiscard, bool transformFeedbackActive)
 {
-    ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout);
-    ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer);
-    ShaderExecutable *geometryExe = programBinary->getGeometryExecutable();
+    ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation());
+
+    ShaderExecutable *vertexExe = NULL;
+    gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ShaderExecutable *pixelExe = NULL;
+    error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ShaderExecutable *geometryExe = programD3D->getGeometryExecutable();
 
     ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL);
 
@@ -1433,16 +1529,14 @@ gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::V
 
     if (dirtyUniforms)
     {
-        programBinary->dirtyAllUniforms();
+        programD3D->dirtyAllUniforms();
     }
 
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Renderer11::applyUniforms(const gl::ProgramBinary &programBinary)
+gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray)
 {
-    const std::vector<gl::LinkedUniform*> &uniformArray = programBinary.getUniforms();
-
     unsigned int totalRegisterCountVS = 0;
     unsigned int totalRegisterCountPS = 0;
 
@@ -1466,7 +1560,7 @@ gl::Error Renderer11::applyUniforms(const gl::ProgramBinary &programBinary)
         }
     }
 
-    const ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary.getImplementation());
+    const ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(&program);
     const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getVertexUniformStorage());
     const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getFragmentUniformStorage());
     ASSERT(vertexUniformStorage);
@@ -1598,7 +1692,7 @@ gl::Error Renderer11::applyUniforms(const gl::ProgramBinary &programBinary)
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
+gl::Error Renderer11::clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer)
 {
     gl::Error error = mClear->clearFramebuffer(clearParams, frameBuffer);
     if (error.isError())
@@ -1626,14 +1720,12 @@ void Renderer11::markAllStateDirty()
     for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId)
     {
         mForceSetVertexSamplerStates[vsamplerId] = true;
-        mCurVertexSRVs[vsamplerId] = NULL;
     }
 
     ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelSRVs.size());
     for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId)
     {
         mForceSetPixelSamplerStates[fsamplerId] = true;
-        mCurPixelSRVs[fsamplerId] = NULL;
     }
 
     mForceSetBlendState = true;
@@ -1746,32 +1838,20 @@ bool Renderer11::testDeviceResettable()
         return false;
     }
 
-    D3D_FEATURE_LEVEL featureLevels[] =
-    {
-        D3D_FEATURE_LEVEL_11_0,
-        D3D_FEATURE_LEVEL_10_1,
-        D3D_FEATURE_LEVEL_10_0,
-#if !defined(ANGLE_ENABLE_D3D9)
-        D3D_FEATURE_LEVEL_9_3,
-        D3D_FEATURE_LEVEL_9_2,
-        D3D_FEATURE_LEVEL_9_1,
-#endif
-    };
-
     ID3D11Device* dummyDevice;
     D3D_FEATURE_LEVEL dummyFeatureLevel;
     ID3D11DeviceContext* dummyContext;
 
     HRESULT result = D3D11CreateDevice(NULL,
-                                       D3D_DRIVER_TYPE_HARDWARE,
+                                       mDriverType,
                                        NULL,
                                        #if defined(_DEBUG)
                                        D3D11_CREATE_DEVICE_DEBUG,
                                        #else
                                        0,
                                        #endif
-                                       featureLevels,
-                                       ArraySize(featureLevels),
+                                       mAvailableFeatureLevels.data(),
+                                       mAvailableFeatureLevels.size(),
                                        D3D11_SDK_VERSION,
                                        &dummyDevice,
                                        &dummyFeatureLevel,
@@ -1939,119 +2019,37 @@ int Renderer11::getMaxSwapInterval() const
     return 4;
 }
 
-bool Renderer11::copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source)
-{
-    if (source && dest)
-    {
-        TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source);
-        TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest);
-
-        mDeviceContext->CopyResource(dest11->getResource(), source11->getResource());
-
-        dest11->invalidateSwizzleCache();
-
-        return true;
-    }
-
-    return false;
-}
-
-bool Renderer11::copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source)
-{
-    if (source && dest)
-    {
-        TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source);
-        TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest);
-
-        mDeviceContext->CopyResource(dest11->getResource(), source11->getResource());
-
-        dest11->invalidateSwizzleCache();
-
-        return true;
-    }
-
-    return false;
-}
-
-bool Renderer11::copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source)
-{
-    if (source && dest)
-    {
-        TextureStorage11_3D *source11 = TextureStorage11_3D::makeTextureStorage11_3D(source);
-        TextureStorage11_3D *dest11 = TextureStorage11_3D::makeTextureStorage11_3D(dest);
-
-        mDeviceContext->CopyResource(dest11->getResource(), source11->getResource());
-
-        dest11->invalidateSwizzleCache();
-
-        return true;
-    }
-
-    return false;
-}
-
-bool Renderer11::copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source)
-{
-    if (source && dest)
-    {
-        TextureStorage11_2DArray *source11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(source);
-        TextureStorage11_2DArray *dest11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(dest);
-
-        mDeviceContext->CopyResource(dest11->getResource(), source11->getResource());
-
-        dest11->invalidateSwizzleCache();
-
-        return true;
-    }
-
-    return false;
-}
-
-bool Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                             GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
+gl::Error Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                  GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
 {
     gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
-    if (!colorbuffer)
-    {
-        ERR("Failed to retrieve the color buffer from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(colorbuffer);
 
-    RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
-    if (!sourceRenderTarget)
+    RenderTarget11 *sourceRenderTarget = NULL;
+    gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(sourceRenderTarget);
 
     ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
-    if (!source)
-    {
-        ERR("Failed to retrieve the render target view from the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(source);
 
     TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage);
-    if (!storage11)
-    {
-        ERR("Failed to retrieve the texture storage from the destination.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(storage11);
 
     gl::ImageIndex index = gl::ImageIndex::Make2D(level);
-    RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index));
-    if (!destRenderTarget)
+    RenderTarget *destRenderTarget = NULL;
+    error = storage11->getRenderTarget(index, &destRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the destination storage.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(destRenderTarget);
 
-    ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
-    if (!dest)
-    {
-        ERR("Failed to retrieve the render target view from the destination render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView();
+    ASSERT(dest);
 
     gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
     gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
@@ -2061,59 +2059,48 @@ bool Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &
 
     // Use nearest filtering because source and destination are the same size for the direct
     // copy
-    bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
-                                  destFormat, GL_NEAREST);
+    mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
+    if (error.isError())
+    {
+        return error;
+    }
 
     storage11->invalidateSwizzleCacheLevel(level);
 
-    return ret;
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                               GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
+gl::Error Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                    GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
 {
     gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
-    if (!colorbuffer)
-    {
-        ERR("Failed to retrieve the color buffer from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(colorbuffer);
 
-    RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
-    if (!sourceRenderTarget)
+    RenderTarget11 *sourceRenderTarget = NULL;
+    gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(sourceRenderTarget);
 
     ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
-    if (!source)
-    {
-        ERR("Failed to retrieve the render target view from the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(source);
 
     TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage);
-    if (!storage11)
-    {
-        ERR("Failed to retrieve the texture storage from the destination.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(storage11);
 
     gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
-    RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index));
-    if (!destRenderTarget)
+    RenderTarget *destRenderTarget = NULL;
+    error = storage11->getRenderTarget(index, &destRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the destination storage.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(destRenderTarget);
 
-    ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
-    if (!dest)
-    {
-        ERR("Failed to retrieve the render target view from the destination render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView();
+    ASSERT(dest);
 
     gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
     gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
@@ -2123,59 +2110,48 @@ bool Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle
 
     // Use nearest filtering because source and destination are the same size for the direct
     // copy
-    bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
-                                  destFormat, GL_NEAREST);
+    error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
+    if (error.isError())
+    {
+        return error;
+    }
 
     storage11->invalidateSwizzleCacheLevel(level);
 
-    return ret;
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                             GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                  GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
 {
     gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
-    if (!colorbuffer)
-    {
-        ERR("Failed to retrieve the color buffer from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(colorbuffer);
 
-    RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
-    if (!sourceRenderTarget)
+    RenderTarget11 *sourceRenderTarget = NULL;
+    gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(sourceRenderTarget);
 
     ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
-    if (!source)
-    {
-        ERR("Failed to retrieve the render target view from the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(source);
 
     TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage);
-    if (!storage11)
-    {
-        ERR("Failed to retrieve the texture storage from the destination.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(storage11);
 
     gl::ImageIndex index = gl::ImageIndex::Make3D(level, zOffset);
-    RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index));
-    if (!destRenderTarget)
+    RenderTarget *destRenderTarget = NULL;
+    error = storage11->getRenderTarget(index, &destRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the destination storage.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(destRenderTarget);
 
-    ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
-    if (!dest)
-    {
-        ERR("Failed to retrieve the render target view from the destination render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView();
+    ASSERT(dest);
 
     gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
     gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
@@ -2185,61 +2161,48 @@ bool Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &
 
     // Use nearest filtering because source and destination are the same size for the direct
     // copy
-    bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
-                                  destFormat, GL_NEAREST);
+    error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
+    if (error.isError())
+    {
+        return error;
+    }
 
     storage11->invalidateSwizzleCacheLevel(level);
 
-    return ret;
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                                  GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                       GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
 {
     gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
-    if (!colorbuffer)
-    {
-        ERR("Failed to retrieve the color buffer from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(colorbuffer);
 
-    RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
-    if (!sourceRenderTarget)
+    RenderTarget11 *sourceRenderTarget = NULL;
+    gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(sourceRenderTarget);
 
     ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
-    if (!source)
-    {
-        ERR("Failed to retrieve the render target view from the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(source);
 
     TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage);
-    if (!storage11)
-    {
-        SafeRelease(source);
-        ERR("Failed to retrieve the texture storage from the destination.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(storage11);
 
     gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zOffset);
-    RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index));
-    if (!destRenderTarget)
+    RenderTarget *destRenderTarget = NULL;
+    error = storage11->getRenderTarget(index, &destRenderTarget);
+    if (error.isError())
     {
-        SafeRelease(source);
-        ERR("Failed to retrieve the render target from the destination storage.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(destRenderTarget);
 
-    ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
-    if (!dest)
-    {
-        ERR("Failed to retrieve the render target view from the destination render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView();
+    ASSERT(dest);
 
     gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
     gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
@@ -2249,12 +2212,15 @@ bool Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectan
 
     // Use nearest filtering because source and destination are the same size for the direct
     // copy
-    bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
-                                  destFormat, GL_NEAREST);
+    error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
+    if (error.isError())
+    {
+        return error;
+    }
 
     storage11->invalidateSwizzleCacheLevel(level);
 
-    return ret;
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Renderer11::unapplyRenderTargets()
@@ -2277,39 +2243,150 @@ void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView
     }
 }
 
-RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
+gl::Error Renderer11::createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT)
 {
     SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
-    RenderTarget11 *renderTarget = NULL;
+    *outRT = new SurfaceRenderTarget11(swapChain11, depth);
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT)
+{
+    const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format);
 
-    if (depth)
+    const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format);
+    GLuint supportedSamples = textureCaps.getNearestSamples(samples);
+
+    if (width > 0 && height > 0)
     {
-        // Note: depth stencil may be NULL for 0 sized surfaces
-        renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(),
-                                          swapChain11->getDepthStencilTexture(),
-                                          swapChain11->getDepthStencilShaderResource(),
-                                          swapChain11->getWidth(), swapChain11->getHeight(), 1);
+        // Create texture resource
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width = width;
+        desc.Height = height;
+        desc.MipLevels = 1;
+        desc.ArraySize = 1;
+        desc.Format = formatInfo.texFormat;
+        desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage = D3D11_USAGE_DEFAULT;
+        desc.CPUAccessFlags = 0;
+        desc.MiscFlags = 0;
+
+        // If a rendertarget or depthstencil format exists for this texture format,
+        // we'll flag it to allow binding that way. Shader resource views are a little
+        // more complicated.
+        bool bindRTV = false, bindDSV = false, bindSRV = false;
+        bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
+        bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
+        if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+        {
+            // Multisample targets flagged for binding as depth stencil cannot also be
+            // flagged for binding as SRV, so make certain not to add the SRV flag for
+            // these targets.
+            bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1);
+        }
+
+        desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET   : 0) |
+                         (bindDSV ? D3D11_BIND_DEPTH_STENCIL   : 0) |
+                         (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0);
+
+        // The format must be either an RTV or a DSV
+        ASSERT(bindRTV != bindDSV);
+
+        ID3D11Texture2D *texture = NULL;
+        HRESULT result = mDevice->CreateTexture2D(&desc, NULL, &texture);
+        if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target texture, result: 0x%X.", result);
+        }
+
+        ID3D11ShaderResourceView *srv = NULL;
+        if (bindSRV)
+        {
+            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+            srvDesc.Format = formatInfo.srvFormat;
+            srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+            srvDesc.Texture2D.MostDetailedMip = 0;
+            srvDesc.Texture2D.MipLevels = 1;
+
+            result = mDevice->CreateShaderResourceView(texture, &srvDesc, &srv);
+            if (FAILED(result))
+            {
+                ASSERT(result == E_OUTOFMEMORY);
+                SafeRelease(texture);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target shader resource view, result: 0x%X.", result);
+            }
+        }
+
+        if (bindDSV)
+        {
+            D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+            dsvDesc.Format = formatInfo.dsvFormat;
+            dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS;
+            dsvDesc.Texture2D.MipSlice = 0;
+            dsvDesc.Flags = 0;
+
+            ID3D11DepthStencilView *dsv = NULL;
+            result = mDevice->CreateDepthStencilView(texture, &dsvDesc, &dsv);
+            if (FAILED(result))
+            {
+                ASSERT(result == E_OUTOFMEMORY);
+                SafeRelease(texture);
+                SafeRelease(srv);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target depth stencil view, result: 0x%X.", result);
+            }
+
+            *outRT = new TextureRenderTarget11(dsv, texture, srv, format, width, height, 1, supportedSamples);
+
+            SafeRelease(dsv);
+        }
+        else if (bindRTV)
+        {
+            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+            rtvDesc.Format = formatInfo.rtvFormat;
+            rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
+            rtvDesc.Texture2D.MipSlice = 0;
+
+            ID3D11RenderTargetView *rtv = NULL;
+            result = mDevice->CreateRenderTargetView(texture, &rtvDesc, &rtv);
+            if (FAILED(result))
+            {
+                ASSERT(result == E_OUTOFMEMORY);
+                SafeRelease(texture);
+                SafeRelease(srv);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target render target view, result: 0x%X.", result);
+            }
+
+            if (formatInfo.dataInitializerFunction != NULL)
+            {
+                const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
+                mDeviceContext->ClearRenderTargetView(rtv, clearValues);
+            }
+
+            *outRT = new TextureRenderTarget11(rtv, texture, srv, format, width, height, 1, supportedSamples);
+
+            SafeRelease(rtv);
+        }
+        else
+        {
+            UNREACHABLE();
+        }
+
+        SafeRelease(texture);
+        SafeRelease(srv);
     }
     else
     {
-        // Note: render target may be NULL for 0 sized surfaces
-        renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(),
-                                          swapChain11->getOffscreenTexture(),
-                                          swapChain11->getRenderTargetShaderResource(),
-                                          swapChain11->getWidth(), swapChain11->getHeight(), 1);
+        *outRT = new TextureRenderTarget11(reinterpret_cast<ID3D11RenderTargetView*>(NULL), NULL, NULL, format, width, height, 1, supportedSamples);
     }
-    return renderTarget;
-}
 
-RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples)
-{
-    RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples);
-    return renderTarget;
+    return gl::Error(GL_NO_ERROR);
 }
 
-ShaderImpl *Renderer11::createShader(GLenum type)
+ShaderImpl *Renderer11::createShader(const gl::Data &data, GLenum type)
 {
-    return new ShaderD3D(type, this);
+    return new ShaderD3D(data, type, this);
 }
 
 ProgramImpl *Renderer11::createProgram()
@@ -2322,22 +2399,23 @@ void Renderer11::releaseShaderCompiler()
     ShaderD3D::releaseCompiler();
 }
 
-ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type,
-                                             const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
-                                             bool separatedOutputBuffers)
+gl::Error Renderer11::loadExecutable(const void *function, size_t length, ShaderType type,
+                                     const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+                                     bool separatedOutputBuffers, ShaderExecutable **outExecutable)
 {
-    ShaderExecutable11 *executable = NULL;
-    HRESULT result;
-
     switch (type)
     {
-      case rx::SHADER_VERTEX:
+      case SHADER_VERTEX:
         {
             ID3D11VertexShader *vertexShader = NULL;
             ID3D11GeometryShader *streamOutShader = NULL;
 
-            result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader);
+            HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader);
             ASSERT(SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result);
+            }
 
             if (transformFeedbackVaryings.size() > 0)
             {
@@ -2363,99 +2441,116 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length
                 result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(),
                                                                        NULL, 0, 0, NULL, &streamOutShader);
                 ASSERT(SUCCEEDED(result));
+                if (FAILED(result))
+                {
+                    return gl::Error(GL_OUT_OF_MEMORY, "Failed to create steam output shader, result: 0x%X.", result);
+                }
             }
 
-            if (vertexShader)
-            {
-                executable = new ShaderExecutable11(function, length, vertexShader, streamOutShader);
-            }
+            *outExecutable = new ShaderExecutable11(function, length, vertexShader, streamOutShader);
         }
         break;
-      case rx::SHADER_PIXEL:
+      case SHADER_PIXEL:
         {
             ID3D11PixelShader *pixelShader = NULL;
 
-            result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader);
+            HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader);
             ASSERT(SUCCEEDED(result));
-
-            if (pixelShader)
+            if (FAILED(result))
             {
-                executable = new ShaderExecutable11(function, length, pixelShader);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader, result: 0x%X.", result);
             }
+
+            *outExecutable = new ShaderExecutable11(function, length, pixelShader);
         }
         break;
-      case rx::SHADER_GEOMETRY:
+      case SHADER_GEOMETRY:
         {
             ID3D11GeometryShader *geometryShader = NULL;
 
-            result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader);
+            HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader);
             ASSERT(SUCCEEDED(result));
-
-            if (geometryShader)
+            if (FAILED(result))
             {
-                executable = new ShaderExecutable11(function, length, geometryShader);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create geometry shader, result: 0x%X.", result);
             }
+
+            *outExecutable = new ShaderExecutable11(function, length, geometryShader);
         }
         break;
       default:
         UNREACHABLE();
-        break;
+        return gl::Error(GL_INVALID_OPERATION);
     }
 
-    return executable;
+    return gl::Error(GL_NO_ERROR);
 }
 
-ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
-                                                  const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
-                                                  bool separatedOutputBuffers, D3DWorkaroundType workaround)
+gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
+                                          const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+                                          bool separatedOutputBuffers, D3DWorkaroundType workaround,
+                                          ShaderExecutable **outExectuable)
 {
     const char *profileType = NULL;
     switch (type)
     {
-      case rx::SHADER_VERTEX:
+      case SHADER_VERTEX:
         profileType = "vs";
         break;
-      case rx::SHADER_PIXEL:
+      case SHADER_PIXEL:
         profileType = "ps";
         break;
-      case rx::SHADER_GEOMETRY:
+      case SHADER_GEOMETRY:
         profileType = "gs";
         break;
       default:
         UNREACHABLE();
-        return NULL;
+        return gl::Error(GL_INVALID_OPERATION);
     }
 
-    const char *profileVersion = NULL;
+    unsigned int profileMajorVersion = 0;
+    unsigned int profileMinorVersion = 0;
+    const char *profileSuffix = NULL;
     switch (mFeatureLevel)
     {
       case D3D_FEATURE_LEVEL_11_0:
-        profileVersion = "5_0";
+        profileMajorVersion = 5;
+        profileMinorVersion = 0;
         break;
       case D3D_FEATURE_LEVEL_10_1:
-        profileVersion = "4_1";
+        profileMajorVersion = 4;
+        profileMinorVersion = 1;
         break;
       case D3D_FEATURE_LEVEL_10_0:
-        profileVersion = "4_0";
+        profileMajorVersion = 4;
+        profileMinorVersion = 0;
         break;
       case D3D_FEATURE_LEVEL_9_3:
-        profileVersion = "4_0_level_9_3";
+        profileMajorVersion = 4;
+        profileMinorVersion = 0;
+        profileSuffix = "_level_9_3";
         break;
       case D3D_FEATURE_LEVEL_9_2:
-        profileVersion = "4_0_level_9_2";
+        profileMajorVersion = 4;
+        profileMinorVersion = 0;
+        profileSuffix = "_level_9_2";
         break;
       case D3D_FEATURE_LEVEL_9_1:
-        profileVersion = "4_0_level_9_1";
+        profileMajorVersion = 4;
+        profileMinorVersion = 0;
+        profileSuffix = "_level_9_1";
         break;
+      break;
       default:
         UNREACHABLE();
-        return NULL;
+        return gl::Error(GL_INVALID_OPERATION);
     }
 
-    char profile[32];
-    snprintf(profile, ArraySize(profile), "%s_%s", profileType, profileVersion);
+    std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
+    if (profileSuffix)
+        profile += profileSuffix;
 
-    UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL0;
+    UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;
 
     if (gl::perfActive())
     {
@@ -2464,44 +2559,51 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch
 #endif
 
         flags |= D3DCOMPILE_DEBUG;
-
-        std::string sourcePath = getTempPath();
-        std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL);
-        writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
     }
 
     // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
     // Try the default flags first and if compilation fails, try some alternatives.
-    const UINT extraFlags[] =
-    {
-        flags,
-        flags | D3DCOMPILE_SKIP_VALIDATION,
-        flags | D3DCOMPILE_SKIP_OPTIMIZATION
-    };
+    std::vector<CompileConfig> configs;
+    configs.push_back(CompileConfig(flags,                                "default"          ));
+    configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION,   "skip validation"  ));
+    configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));
 
-    const static char *extraFlagNames[] =
-    {
-        "default",
-        "skip validation",
-        "skip optimization"
-    };
+    D3D_SHADER_MACRO loopMacros[] = { {"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0} };
 
-    int attempts = ArraySize(extraFlags);
+    ID3DBlob *binary = NULL;
+    std::string debugInfo;
+    gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary, &debugInfo);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts);
+    // It's possible that binary is NULL if the compiler failed in all configurations.  Set the executable to NULL
+    // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK.
     if (!binary)
     {
-        return NULL;
+        *outExectuable = NULL;
+        return gl::Error(GL_NO_ERROR);
     }
 
-    ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type,
-                                                  transformFeedbackVaryings, separatedOutputBuffers);
+    error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
+                           transformFeedbackVaryings, separatedOutputBuffers, outExectuable);
+
     SafeRelease(binary);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!debugInfo.empty())
+    {
+        (*outExectuable)->appendDebugInfo(debugInfo);
+    }
 
-    return executable;
+    return gl::Error(GL_NO_ERROR);
 }
 
-rx::UniformStorage *Renderer11::createUniformStorage(size_t storageSize)
+UniformStorage *Renderer11::createUniformStorage(size_t storageSize)
 {
     return new UniformStorage11(this, storageSize);
 }
@@ -2531,9 +2633,14 @@ QueryImpl *Renderer11::createQuery(GLenum type)
     return new Query11(this, type);
 }
 
-FenceImpl *Renderer11::createFence()
+FenceNVImpl *Renderer11::createFenceNV()
 {
-    return new Fence11(this);
+    return new FenceNV11(this);
+}
+
+FenceSyncImpl *Renderer11::createFenceSync()
+{
+    return new FenceSync11(this);
 }
 
 TransformFeedbackImpl* Renderer11::createTransformFeedback()
@@ -2576,82 +2683,77 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
     return true;
 }
 
-bool Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
-                                         GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
+gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+                                              GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
 {
     ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
     return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea);
 }
 
-bool Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource)
+gl::Error Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, ID3D11Texture2D **texture2DOut)
+
 {
-    ASSERT(colorbuffer != NULL);
+    ASSERT(colorbuffer);
 
-    RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
-    if (renderTarget)
+    RenderTarget11 *renderTarget = NULL;
+    gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget);
+    if (error.isError())
     {
-        *subresourceIndex = renderTarget->getSubresourceIndex();
+        return error;
+    }
 
-        ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView();
-        if (colorBufferRTV)
-        {
-            ID3D11Resource *textureResource = NULL;
-            colorBufferRTV->GetResource(&textureResource);
+    ID3D11Resource *renderTargetResource = renderTarget->getTexture();
+    ASSERT(renderTargetResource);
 
-            if (textureResource)
-            {
-                HRESULT result = textureResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)resource);
-                SafeRelease(textureResource);
+    *subresourceIndexOut = renderTarget->getSubresourceIndex();
+    *texture2DOut = d3d11::DynamicCastComObject<ID3D11Texture2D>(renderTargetResource);
 
-                if (SUCCEEDED(result))
-                {
-                    return true;
-                }
-                else
-                {
-                    ERR("Failed to extract the ID3D11Texture2D from the render target resource, "
-                        "HRESULT: 0x%X.", result);
-                }
-            }
-        }
+    if (!(*texture2DOut))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the ID3D11Texture2D from a RenderTarget");
     }
 
-    return false;
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
-                          const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter)
+gl::Error Renderer11::blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect,
+                               const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
+                               const gl::Rectangle *scissor, bool blitRenderTarget,
+                               bool blitDepth, bool blitStencil, GLenum filter)
 {
     if (blitRenderTarget)
     {
         gl::FramebufferAttachment *readBuffer = readTarget->getReadColorbuffer();
+        ASSERT(readBuffer);
 
-        if (!readBuffer)
+        RenderTarget *readRenderTarget = NULL;
+        gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget);
+        if (error.isError())
         {
-            ERR("Failed to retrieve the read buffer from the read framebuffer.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
+            return error;
         }
-
-        RenderTarget *readRenderTarget = GetAttachmentRenderTarget(readBuffer);
+        ASSERT(readRenderTarget);
 
         for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
         {
             if (drawTarget->isEnabledColorAttachment(colorAttachment))
             {
                 gl::FramebufferAttachment *drawBuffer = drawTarget->getColorbuffer(colorAttachment);
+                ASSERT(drawBuffer);
 
-                if (!drawBuffer)
+                RenderTarget *drawRenderTarget = NULL;
+                error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget);
+                if (error.isError())
                 {
-                    ERR("Failed to retrieve the draw buffer from the draw framebuffer.");
-                    return gl::error(GL_OUT_OF_MEMORY, false);
+                    return error;
                 }
+                ASSERT(drawRenderTarget);
 
-                RenderTarget *drawRenderTarget = GetAttachmentRenderTarget(drawBuffer);
-
-                if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor,
-                                          blitRenderTarget, false, false))
+                error = blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, blitRenderTarget,
+                                             false, false);
+                if (error.isError())
                 {
-                    return false;
+                    return error;
                 }
             }
         }
@@ -2660,78 +2762,88 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read
     if (blitDepth || blitStencil)
     {
         gl::FramebufferAttachment *readBuffer = readTarget->getDepthOrStencilbuffer();
-        gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer();
+        ASSERT(readBuffer);
 
-        if (!readBuffer)
+        RenderTarget *readRenderTarget = NULL;
+        gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget);
+        if (error.isError())
         {
-            ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
+            return error;
         }
+        ASSERT(readRenderTarget);
 
-        if (!drawBuffer)
+        gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer();
+        ASSERT(drawBuffer);
+
+        RenderTarget *drawRenderTarget = NULL;
+        error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget);
+        if (error.isError())
         {
-            ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
+            return error;
         }
+        ASSERT(drawRenderTarget);
 
-        RenderTarget *readRenderTarget = GetAttachmentRenderTarget(readBuffer);
-        RenderTarget *drawRenderTarget = GetAttachmentRenderTarget(drawBuffer);
-        ASSERT(readRenderTarget && drawRenderTarget);
-
-        if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor,
-                                  false, blitDepth, blitStencil))
+        error = blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, false,
+                                     blitDepth, blitStencil);
+        if (error.isError())
         {
-            return false;
+            return error;
         }
     }
 
     invalidateFramebufferSwizzles(drawTarget);
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+gl::Error Renderer11::readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
                                  GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels)
 {
     ID3D11Texture2D *colorBufferTexture = NULL;
     unsigned int subresourceIndex = 0;
 
     gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
+    ASSERT(colorbuffer);
 
-    if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
+    gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture);
+    if (error.isError())
     {
-        gl::Rectangle area;
-        area.x = x;
-        area.y = y;
-        area.width = width;
-        area.height = height;
+        return error;
+    }
 
-        gl::Buffer *packBuffer = pack.pixelBuffer.get();
-        if (packBuffer != NULL)
-        {
-            rx::Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation());
-            PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast<ptrdiff_t>(pixels));
+    gl::Rectangle area;
+    area.x = x;
+    area.y = y;
+    area.width = width;
+    area.height = height;
 
-            gl::Error error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams);
-            if (error.isError())
-            {
-                return error;
-            }
+    gl::Buffer *packBuffer = pack.pixelBuffer.get();
+    if (packBuffer != NULL)
+    {
+        Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation());
+        PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast<ptrdiff_t>(pixels));
 
-            packBuffer->getIndexRangeCache()->clear();
-        }
-        else
+        error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams);
+        if (error.isError())
         {
-            gl::Error error = readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels);
-            if (error.isError())
-            {
-                return error;
-            }
+            SafeRelease(colorBufferTexture);
+            return error;
         }
 
-        SafeRelease(colorBufferTexture);
+        packBuffer->getIndexRangeCache()->clear();
+    }
+    else
+    {
+        error = readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels);
+        if (error.isError())
+        {
+            SafeRelease(colorBufferTexture);
+            return error;
+        }
     }
 
+    SafeRelease(colorBufferTexture);
+
     return gl::Error(GL_NO_ERROR);
 }
 
@@ -2740,11 +2852,11 @@ Image *Renderer11::createImage()
     return new Image11();
 }
 
-void Renderer11::generateMipmap(Image *dest, Image *src)
+gl::Error Renderer11::generateMipmap(Image *dest, Image *src)
 {
     Image11 *dest11 = Image11::makeImage11(dest);
     Image11 *src11 = Image11::makeImage11(src);
-    Image11::generateMipmap(dest11, src11);
+    return Image11::generateMipmap(dest11, src11);
 }
 
 TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain)
@@ -2788,6 +2900,19 @@ TextureImpl *Renderer11::createTexture(GLenum target)
     return NULL;
 }
 
+RenderbufferImpl *Renderer11::createRenderbuffer()
+{
+    RenderbufferD3D *renderbuffer = new RenderbufferD3D(this);
+    return renderbuffer;
+}
+
+RenderbufferImpl *Renderer11::createRenderbuffer(SwapChain *swapChain, bool depth)
+{
+    RenderbufferD3D *renderbuffer = new RenderbufferD3D(this);
+    renderbuffer->setStorage(swapChain, depth);
+    return renderbuffer;
+}
+
 gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format,
                                       GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels)
 {
@@ -2882,22 +3007,25 @@ gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int sub
     SafeRelease(srcTex);
 
     PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0);
-    packPixels(stagingTex, packParams, pixels);
+    gl::Error error = packPixels(stagingTex, packParams, pixels);
 
     SafeRelease(stagingTex);
 
-    return gl::Error(GL_NO_ERROR);
+    return error;
 }
 
-void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams &params, uint8_t *pixelsOut)
+gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams &params, uint8_t *pixelsOut)
 {
     D3D11_TEXTURE2D_DESC textureDesc;
     readTexture->GetDesc(&textureDesc);
 
     D3D11_MAPPED_SUBRESOURCE mapping;
     HRESULT hr = mDeviceContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &mapping);
-    UNUSED_ASSERTION_VARIABLE(hr);
-    ASSERT(SUCCEEDED(hr));
+    if (FAILED(hr))
+    {
+        ASSERT(hr == E_OUTOFMEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal texture for reading, result: 0x%X.", hr);
+    }
 
     uint8_t *source;
     int inputPitch;
@@ -2968,24 +3096,23 @@ void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams
     }
 
     mDeviceContext->Unmap(readTexture, 0);
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
-                                      RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
-                                      bool colorBlit, bool depthBlit, bool stencilBlit)
+gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
+                                           RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
+                                           bool colorBlit, bool depthBlit, bool stencilBlit)
 {
     // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
     // it should never be the case that both color and depth/stencil need to be blitted at
     // at the same time.
     ASSERT(colorBlit != (depthBlit || stencilBlit));
 
-    bool result = true;
-
     RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget);
     if (!drawRenderTarget)
     {
-        ERR("Failed to retrieve the draw render target from the draw framebuffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal draw render target from the draw framebuffer.");
     }
 
     ID3D11Resource *drawTexture = drawRenderTarget11->getTexture();
@@ -2996,8 +3123,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
     RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget);
     if (!readRenderTarget)
     {
-        ERR("Failed to retrieve the read render target from the read framebuffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target from the read framebuffer.");
     }
 
     ID3D11Resource *readTexture = NULL;
@@ -3019,7 +3145,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
             if (FAILED(hresult))
             {
                 SafeRelease(readTexture);
-                return gl::error(GL_OUT_OF_MEMORY, false);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader resource view to resolve multisampled framebuffer.");
             }
         }
     }
@@ -3036,8 +3162,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
     {
         SafeRelease(readTexture);
         SafeRelease(readSRV);
-        ERR("Failed to retrieve the read render target view from the read render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target view from the read render target.");
     }
 
     gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
@@ -3063,6 +3188,8 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
     const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getActualFormat());
     bool partialDSBlit = (actualFormatInfo.depthBits > 0 && depthBlit) != (actualFormatInfo.stencilBits > 0 && stencilBlit);
 
+    gl::Error result(GL_NO_ERROR);
+
     if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() &&
         !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
         (!(depthBlit || stencilBlit) || wholeBufferCopy))
@@ -3109,7 +3236,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
 
         mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, dstX, dstY, 0,
                                               readTexture, readSubresource, pSrcBox);
-        result = true;
+        result = gl::Error(GL_NO_ERROR);
     }
     else
     {
@@ -3190,7 +3317,8 @@ void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *atta
     ASSERT(attachment->isTexture());
     gl::Texture *texture = attachment->getTexture();
 
-    TextureStorage *texStorage = texture->getNativeTexture();
+    TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+    TextureStorage *texStorage = textureD3D->getNativeTexture();
     if (texStorage)
     {
         TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage);
@@ -3204,7 +3332,7 @@ void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *atta
     }
 }
 
-void Renderer11::invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer)
+void Renderer11::invalidateFramebufferSwizzles(const gl::Framebuffer *framebuffer)
 {
     for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
     {
@@ -3248,7 +3376,7 @@ bool Renderer11::getLUID(LUID *adapterLuid) const
     return true;
 }
 
-rx::VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const
+VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const
 {
     return d3d11::GetVertexFormatInfo(vertexFormat).conversionType;
 }
@@ -3263,4 +3391,30 @@ void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureC
     d3d11_gl::GenerateCaps(mDevice, outCaps, outTextureCaps, outExtensions);
 }
 
+Workarounds Renderer11::generateWorkarounds() const
+{
+    return d3d11::GenerateWorkarounds();
+}
+
+void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv)
+{
+    std::vector<ID3D11ShaderResourceView *> &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+
+    ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size());
+
+    if (currentSRVs[resourceSlot] != srv)
+    {
+        if (shaderType == gl::SAMPLER_VERTEX)
+        {
+            mDeviceContext->VSSetShaderResources(resourceSlot, 1, &srv);
+        }
+        else
+        {
+            mDeviceContext->PSSetShaderResources(resourceSlot, 1, &srv);
+        }
+
+        currentSRVs[resourceSlot] = srv;
+    }
+}
+
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
index 2a53fa1672b..d44bd2fd301 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
@@ -13,12 +13,14 @@
 #include "libGLESv2/angletypes.h"
 #include "common/mathutil.h"
 
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
 #include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h"
 #include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h"
+#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
 #include "libGLESv2/renderer/RenderTarget.h"
 
+#include "libEGL/AttributeMap.h"
+
 namespace gl
 {
 class FramebufferAttachment;
@@ -33,6 +35,7 @@ class StreamingIndexBufferInterface;
 class Blit11;
 class Clear11;
 class PixelTransfer11;
+class RenderTarget11;
 struct PackPixelsParams;
 
 enum
@@ -41,10 +44,10 @@ enum
     MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024
 };
 
-class Renderer11 : public Renderer
+class Renderer11 : public RendererD3D
 {
   public:
-    Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay);
+    Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes);
     virtual ~Renderer11();
 
     static Renderer11 *makeRenderer11(Renderer *renderer);
@@ -55,19 +58,19 @@ class Renderer11 : public Renderer
     virtual int generateConfigs(ConfigDesc **configDescList);
     virtual void deleteConfigs(ConfigDesc *configDescList);
 
-    virtual void sync(bool block);
+    virtual gl::Error sync(bool block);
 
-    virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
+    virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
 
     virtual gl::Error generateSwizzle(gl::Texture *texture);
-    virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
+    virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler);
     virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture);
 
     virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]);
 
     virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
-    virtual gl::Error setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
-                                    unsigned int sampleMask);
+    gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
+                            unsigned int sampleMask) override;
     virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
                                            int stencilBackRef, bool frontFaceCCW);
 
@@ -76,32 +79,32 @@ class Renderer11 : public Renderer
                              bool ignoreViewport);
 
     virtual bool applyPrimitiveType(GLenum mode, GLsizei count);
-    virtual gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer);
+    gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override;
     virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
                                    bool rasterizerDiscard, bool transformFeedbackActive);
-    virtual gl::Error applyUniforms(const gl::ProgramBinary &programBinary);
-    virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[],
-                                        GLint first, GLsizei count, GLsizei instances);
+
+    virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray);
+    virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances);
     virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
-    virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]);
+    virtual void applyTransformFeedbackBuffers(const gl::State &state);
 
     virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive);
     virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
                                    gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
 
-    virtual gl::Error clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
+    gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) override;
 
     virtual void markAllStateDirty();
 
     // lost device
-    void notifyDeviceLost();
-    virtual bool isDeviceLost();
-    virtual bool testDeviceLost(bool notify);
-    virtual bool testDeviceResettable();
+    void notifyDeviceLost() override;
+    bool isDeviceLost() override;
+    bool testDeviceLost(bool notify) override;
+    bool testDeviceResettable() override;
 
-    virtual DWORD getAdapterVendor() const;
-    virtual std::string getRendererDescription() const;
-    virtual GUID getAdapterIdentifier() const;
+    DWORD getAdapterVendor() const override;
+    std::string getRendererDescription() const override;
+    GUID getAdapterIdentifier() const override;
 
     virtual unsigned int getReservedVertexUniformVectors() const;
     virtual unsigned int getReservedFragmentUniformVectors() const;
@@ -115,47 +118,43 @@ class Renderer11 : public Renderer
     virtual int getMaxSwapInterval() const;
 
     // Pixel operations
-    virtual bool copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source);
-    virtual bool copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source);
-    virtual bool copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source);
-    virtual bool copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source);
-
-    virtual bool copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                             GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level);
-    virtual bool copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                               GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level);
-    virtual bool copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                             GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
-    virtual bool copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+    virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                  GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level);
+    virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                    GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level);
+    virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
                                   GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
+    virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                       GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
 
-    virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
-                          const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter);
+    gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
+                       const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) override;
 
-    virtual gl::Error readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+    virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
                                  GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
 
     // RenderTarget creation
-    virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth);
-    virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples);
+    virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT);
+    virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT);
 
     // Shader creation
-    virtual ShaderImpl *createShader(GLenum type);
+    virtual ShaderImpl *createShader(const gl::Data &data, GLenum type);
     virtual ProgramImpl *createProgram();
 
     // Shader operations
-    virtual void releaseShaderCompiler();
-    virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
-                                             const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
-                                             bool separatedOutputBuffers);
-    virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
-                                                  const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
-                                                  bool separatedOutputBuffers, D3DWorkaroundType workaround);
+    void releaseShaderCompiler() override;
+    virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type,
+                                     const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+                                     bool separatedOutputBuffers, ShaderExecutable **outExecutable);
+    virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
+                                          const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+                                          bool separatedOutputBuffers, D3DWorkaroundType workaround,
+                                          ShaderExecutable **outExectuable);
     virtual UniformStorage *createUniformStorage(size_t storageSize);
 
     // Image operations
     virtual Image *createImage();
-    virtual void generateMipmap(Image *dest, Image *source);
+    gl::Error generateMipmap(Image *dest, Image *source) override;
     virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
     virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
     virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels);
@@ -165,6 +164,10 @@ class Renderer11 : public Renderer
     // Texture creation
     virtual TextureImpl *createTexture(GLenum target);
 
+    // Renderbuffer creation
+    virtual RenderbufferImpl *createRenderbuffer();
+    virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth);
+
     // Buffer creation
     virtual BufferImpl *createBuffer();
     virtual VertexBuffer *createVertexBuffer();
@@ -175,7 +178,8 @@ class Renderer11 : public Renderer
 
     // Query and Fence creation
     virtual QueryImpl *createQuery(GLenum type);
-    virtual FenceImpl *createFence();
+    virtual FenceNVImpl *createFenceNV();
+    virtual FenceSyncImpl *createFenceSync();
 
     // Transform Feedback creation
     virtual TransformFeedbackImpl* createTransformFeedback();
@@ -183,48 +187,54 @@ class Renderer11 : public Renderer
     // D3D11-renderer specific methods
     ID3D11Device *getDevice() { return mDevice; }
     ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
-    IDXGIFactory *getDxgiFactory() { return mDxgiFactory; };
+    DXGIFactory *getDxgiFactory() { return mDxgiFactory; };
     bool isLevel9() { return mFeatureLevel <= D3D_FEATURE_LEVEL_9_3; }
 
     Blit11 *getBlitter() { return mBlit; }
 
     // Buffer-to-texture and Texture-to-buffer copies
     virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const;
-    virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
-                                         GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
+    virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+                                              GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
+
+    gl::Error getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, ID3D11Texture2D **texture2DOut);
 
-    bool getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource);
     void unapplyRenderTargets();
     void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView);
-    void packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams &params, uint8_t *pixelsOut);
+    gl::Error packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams &params, uint8_t *pixelsOut);
 
     virtual bool getLUID(LUID *adapterLuid) const;
-    virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const;
+    virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const;
     virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const;
 
+    gl::Error readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format,
+                              GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
+
+    void setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv);
+
   private:
     DISALLOW_COPY_AND_ASSIGN(Renderer11);
 
-    virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const;
+    void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override;
+    Workarounds generateWorkarounds() const override;
 
     gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
     gl::Error drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances);
 
-    gl::Error readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format,
-                              GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
-
-    bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
-                              RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
-                              bool colorBlit, bool depthBlit, bool stencilBlit);
+    gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
+                                   RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
+                                   bool colorBlit, bool depthBlit, bool stencilBlit);
     ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
+    void unsetSRVsWithResource(gl::SamplerType shaderType, const ID3D11Resource *resource);
 
     static void invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel);
-    static void invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer);
+    static void invalidateFramebufferSwizzles(const gl::Framebuffer *framebuffer);
 
     HMODULE mD3d11Module;
     HMODULE mDxgiModule;
     EGLNativeDisplayType mDc;
-    EGLint mRequestedDisplay;
+    std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
+    D3D_DRIVER_TYPE mDriverType;
 
     HLSLCompiler mCompiler;
 
@@ -243,7 +253,7 @@ class Renderer11 : public Renderer
     unsigned int mAppliedStencilbufferSerial;
     bool mDepthStencilInitialized;
     bool mRenderTargetDescInitialized;
-    rx::RenderTarget::Desc mRenderTargetDesc;
+    RenderTarget::Desc mRenderTargetDesc;
 
     // Currently applied sampler states
     std::vector<bool> mForceSetVertexSamplerStates;
@@ -292,8 +302,14 @@ class Renderer11 : public Renderer
     unsigned int mAppliedIBOffset;
 
     // Currently applied transform feedback buffers
-    ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
-    GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
+    ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current D3D buffers
+                                                                                        // in use for streamout
+    GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current GL-specified
+                                                                                   // buffer offsets to transform feedback
+                                                                                   // buffers
+    UINT mCurrentD3DOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];  // Tracks the D3D buffer offsets,
+                                                                                 // which may differ from GLs, due
+                                                                                 // to different append behavior
 
     // Currently applied shaders
     ID3D11VertexShader *mAppliedVertexShader;
@@ -339,7 +355,7 @@ class Renderer11 : public Renderer
     IDXGIAdapter *mDxgiAdapter;
     DXGI_ADAPTER_DESC mAdapterDescription;
     char mDescription[128];
-    IDXGIFactory *mDxgiFactory;
+    DXGIFactory *mDxgiFactory;
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
index 4b29be055d3..52c8a816331 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
@@ -6,7 +6,6 @@
 
 // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain.
 
-#include "common/platform.h"
 #include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
@@ -16,12 +15,16 @@
 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h"
 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h"
 
+#include "common/features.h"
+#include "common/NativeWindow.h"
+
 namespace rx
 {
 
-SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
+SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
                          GLenum backBufferFormat, GLenum depthBufferFormat)
-    : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
+    : mRenderer(renderer),
+      SwapChain(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat)
 {
     mSwapChain = NULL;
     mBackBufferTexture = NULL;
@@ -39,8 +42,8 @@ SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDL
     mPassThroughPS = NULL;
     mWidth = -1;
     mHeight = -1;
-    mViewportWidth = -1;
-    mViewportHeight = -1;
+    mRotateL = false;
+    mRotateR = false;
     mSwapInterval = 0;
     mAppCreatedShareHandle = mShareHandle != NULL;
     mPassThroughResourcesInit = false;
@@ -91,11 +94,11 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
     ASSERT(device != NULL);
 
     // D3D11 does not allow zero size textures
-    ASSERT(backbufferWidth >= 1);
-    ASSERT(backbufferHeight >= 1);
+    ASSERT(backbufferWidth != 0);
+    ASSERT(backbufferHeight != 0);
 
     // Preserve the render target content
-#if !defined(ANGLE_PLATFORM_WINRT)
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
     ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
     if (previousOffscreenTexture)
     {
@@ -137,8 +140,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
         D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
         mOffscreenTexture->GetDesc(&offscreenTextureDesc);
 
-        if (offscreenTextureDesc.Width != (UINT)backbufferWidth ||
-            offscreenTextureDesc.Height != (UINT)backbufferHeight ||
+        if (offscreenTextureDesc.Width != UINT(abs(backbufferWidth)) ||
+            offscreenTextureDesc.Height != UINT(abs(backbufferHeight)) ||
             offscreenTextureDesc.Format != backbufferFormatInfo.texFormat ||
             offscreenTextureDesc.MipLevels != 1 ||
             offscreenTextureDesc.ArraySize != 1)
@@ -150,11 +153,11 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
     }
     else
     {
-        const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport();
+        const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport();
 
         D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
-        offscreenTextureDesc.Width = backbufferWidth;
-        offscreenTextureDesc.Height = backbufferHeight;
+        offscreenTextureDesc.Width = abs(backbufferWidth);
+        offscreenTextureDesc.Height = abs(backbufferHeight);
         offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
         offscreenTextureDesc.MipLevels = 1;
         offscreenTextureDesc.ArraySize = 1;
@@ -234,8 +237,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
     if (mDepthBufferFormat != GL_NONE)
     {
         D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
-        depthStencilTextureDesc.Width = backbufferWidth;
-        depthStencilTextureDesc.Height = backbufferHeight;
+        depthStencilTextureDesc.Width = abs(backbufferWidth);
+        depthStencilTextureDesc.Height = abs(backbufferHeight);
         depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat;
         depthStencilTextureDesc.MipLevels = 1;
         depthStencilTextureDesc.ArraySize = 1;
@@ -286,12 +289,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
 
     mWidth = backbufferWidth;
     mHeight = backbufferHeight;
-#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP
-    mViewportWidth = backbufferWidth;
-    mViewportHeight = backbufferHeight;
-#endif
 
-#if !defined(ANGLE_PLATFORM_WINRT)
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
     if (previousOffscreenTexture != NULL)
     {
         D3D11_BOX sourceBox = {0};
@@ -310,7 +309,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
 
         if (mSwapChain)
         {
-            swapRect(0, 0, mWidth, mHeight, SWAP_NORMAL);
+            swapRect(0, 0, mWidth, mHeight);
         }
     }
 #endif
@@ -327,8 +326,16 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
         return EGL_BAD_ACCESS;
     }
 
+    // Windows Phone works around the rotation limitation by using negative values for the swap chain size
+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+    mRotateL = backbufferWidth < 0; // Landscape/InvertedLandscape
+    mRotateR = backbufferHeight < 0; // InvertedPortrait/InvertedLandscape
+    backbufferWidth = abs(backbufferWidth);
+    backbufferHeight = abs(backbufferHeight);
+#endif
+
     // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
-    if (backbufferWidth < 1 || backbufferHeight < 1)
+    if (backbufferWidth == 0 || backbufferHeight == 0)
     {
         return EGL_SUCCESS;
     }
@@ -336,19 +343,15 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
     // Can only call resize if we have already created our swap buffer and resources
     ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
 
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // The swap chain is not directly resized on Windows Phone
     SafeRelease(mBackBufferTexture);
     SafeRelease(mBackBufferRTView);
 
     // Resize swap chain
-    HRESULT result;
-#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP // Windows phone swap chain is never resized, only the texture is
-#if !defined(ANGLE_PLATFORM_WINRT)
-    const int bufferCount = 1;
-#else
-    const int bufferCount = 2;
-#endif
+    DXGI_SWAP_CHAIN_DESC desc;
+    mSwapChain->GetDesc(&desc);
     const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat);
-    result = mSwapChain->ResizeBuffers(bufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0);
+    HRESULT result = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0);
 
     if (FAILED(result))
     {
@@ -364,7 +367,6 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
             return EGL_BAD_ALLOC;
         }
     }
-#endif
 
     result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
     ASSERT(SUCCEEDED(result));
@@ -379,6 +381,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
     {
         d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
     }
+#endif
 
     return resetOffscreenTexture(backbufferWidth, backbufferHeight);
 }
@@ -412,62 +415,14 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
         return EGL_SUCCESS;
     }
 
-    if (mWindow)
+    if (mNativeWindow.getNativeWindow())
     {
         const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat);
 
-        IDXGIFactory *factory = mRenderer->getDxgiFactory();
-
-#if !defined(ANGLE_PLATFORM_WINRT)
-        DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
-        swapChainDesc.BufferDesc.Width = backbufferWidth;
-        swapChainDesc.BufferDesc.Height = backbufferHeight;
-        swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
-        swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
-        swapChainDesc.BufferDesc.Format = backbufferFormatInfo.texFormat;
-        swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
-        swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
-        swapChainDesc.SampleDesc.Count = 1;
-        swapChainDesc.SampleDesc.Quality = 0;
-        swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-        swapChainDesc.BufferCount = 1;
-        swapChainDesc.OutputWindow = mWindow;
-        swapChainDesc.Windowed = TRUE;
-        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
-        swapChainDesc.Flags = 0;
-
-        HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
-#else
-        IDXGIFactory2 *factory2;
-        HRESULT result = factory->QueryInterface(IID_PPV_ARGS(&factory2));
-        ASSERT(SUCCEEDED(result));
-
-        DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
-        swapChainDesc.Width = 0;
-        swapChainDesc.Height = 0;
-        swapChainDesc.Format = backbufferFormatInfo.texFormat;
-        swapChainDesc.SampleDesc.Count = 1;
-        swapChainDesc.SampleDesc.Quality = 0;
-        swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-        swapChainDesc.Stereo = FALSE;
-        swapChainDesc.Flags = 0;
-#if WINAPI_FAMILY==WINAPI_FAMILY_PC_APP
-        swapChainDesc.Scaling = DXGI_SCALING_NONE;
-        swapChainDesc.BufferCount = 2;
-        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
-#elif WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-        swapChainDesc.BufferCount = 1;
-        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
-#endif
+        HRESULT result = mNativeWindow.createSwapChain(device, mRenderer->getDxgiFactory(),
+                                               backbufferFormatInfo.texFormat,
+                                               backbufferWidth, backbufferHeight, &mSwapChain);
 
-        IDXGISwapChain1 *swapChain;
-        result = factory2->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain);
-        mSwapChain = swapChain;
-        HRESULT hr = swapChain->GetDesc1(&swapChainDesc);
-        ASSERT(SUCCEEDED(hr));
-        mViewportWidth = swapChainDesc.Width;
-        mViewportHeight = swapChainDesc.Height;
-#endif
         if (FAILED(result))
         {
             ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
@@ -537,7 +492,7 @@ void SwapChain11::initPassThroughResources()
     samplerDesc.BorderColor[2] = 0.0f;
     samplerDesc.BorderColor[3] = 0.0f;
     samplerDesc.MinLOD = 0;
-    samplerDesc.MaxLOD = FLT_MAX;
+    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
 
     result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
     ASSERT(SUCCEEDED(result));
@@ -563,7 +518,7 @@ void SwapChain11::initPassThroughResources()
 }
 
 // parameters should be validated/clamped by caller
-EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags)
+EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
 {
     if (!mSwapChain)
     {
@@ -573,16 +528,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EG
     ID3D11Device *device = mRenderer->getDevice();
     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
 
-    // Set vertices
-    D3D11_MAPPED_SUBRESOURCE mappedResource;
-    HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
-    if (FAILED(result))
-    {
-        return EGL_BAD_ACCESS;
-    }
-
-    d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
-
     // Create a quad in homogeneous coordinates
     float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
     float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
@@ -594,8 +539,18 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EG
     float u2 = (x + width) / float(mWidth);
     float v2 = (y + height) / float(mHeight);
 
-    const int rotateL = flags & SWAP_ROTATE_90;
-    const int rotateR = flags & SWAP_ROTATE_270;
+    const bool rotateL = mRotateL;
+    const bool rotateR = mRotateR;
+
+    // Set vertices
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    if (FAILED(result))
+    {
+        return EGL_BAD_ACCESS;
+    }
+
+    d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
 
     d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1);
     d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2);
@@ -628,22 +583,23 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EG
 
     // Set the viewport
     D3D11_VIEWPORT viewport;
-    viewport.TopLeftX = 0;
-    viewport.TopLeftY = 0;
-    viewport.Width = mViewportWidth;
-    viewport.Height = mViewportHeight;
+    viewport.TopLeftX = 0.0f;
+    viewport.TopLeftY = 0.0f;
+    const bool invertViewport = (mRotateL || mRotateR) && !(mRotateL && mRotateR);
+    viewport.Width = FLOAT(invertViewport ? mHeight : mWidth);
+    viewport.Height = FLOAT(invertViewport ? mWidth : mHeight);
     viewport.MinDepth = 0.0f;
     viewport.MaxDepth = 1.0f;
     deviceContext->RSSetViewports(1, &viewport);
 
     // Apply textures
-    deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView);
     deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
 
     // Draw
     deviceContext->Draw(4, 0);
 
-#ifdef ANGLE_FORCE_VSYNC_OFF
+#if ANGLE_VSYNC == ANGLE_DISABLED
     result = mSwapChain->Present(0, 0);
 #else
     result = mSwapChain->Present(mSwapInterval, 0);
@@ -667,8 +623,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EG
     }
 
     // Unbind
-    static ID3D11ShaderResourceView *const nullSRV = NULL;
-    deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+    mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
 
     mRenderer->unapplyRenderTargets();
     mRenderer->markAllStateDirty();
@@ -708,8 +663,8 @@ ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
 
 SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
 {
-    ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
-    return static_cast<rx::SwapChain11*>(swapChain);
+    ASSERT(HAS_DYNAMIC_TYPE(SwapChain11*, swapChain));
+    return static_cast<SwapChain11*>(swapChain);
 }
 
 void SwapChain11::recreate()
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h
index b30b78568ae..77509edcd3c 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h
@@ -19,13 +19,13 @@ class Renderer11;
 class SwapChain11 : public SwapChain
 {
   public:
-    SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
+    SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
                 GLenum backBufferFormat, GLenum depthBufferFormat);
     virtual ~SwapChain11();
 
     EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
     virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
-    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags);
+    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
     virtual void recreate();
 
     virtual ID3D11Texture2D *getOffscreenTexture();
@@ -52,13 +52,13 @@ class SwapChain11 : public SwapChain
     Renderer11 *mRenderer;
     EGLint mHeight;
     EGLint mWidth;
-    EGLint mViewportWidth;
-    EGLint mViewportHeight;
+    bool mRotateL;
+    bool mRotateR;
     bool mAppCreatedShareHandle;
     unsigned int mSwapInterval;
     bool mPassThroughResourcesInit;
 
-    IDXGISwapChain *mSwapChain;
+    DXGISwapChain *mSwapChain;
 
     ID3D11Texture2D *mBackBufferTexture;
     ID3D11RenderTargetView *mBackBufferRTView;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
index 91e7147da66..74af27e8b32 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -8,6 +8,9 @@
 // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
 
 #include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h"
+
+#include <tuple>
+
 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
 #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
 #include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
@@ -15,6 +18,7 @@
 #include "libGLESv2/renderer/d3d/d3d11/Blit11.h"
 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
 #include "libGLESv2/renderer/d3d/d3d11/Image11.h"
+#include "libGLESv2/renderer/d3d/MemoryBuffer.h"
 #include "libGLESv2/renderer/d3d/TextureD3D.h"
 #include "libGLESv2/main.h"
 #include "libGLESv2/ImageIndex.h"
@@ -52,46 +56,16 @@ TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle)
 {
 }
 
-bool TextureStorage11::SRVKey::operator==(const SRVKey &rhs) const
-{
-    return baseLevel == rhs.baseLevel &&
-           mipLevels == rhs.mipLevels &&
-           swizzle == rhs.swizzle;
-}
-
-TextureStorage11::SRVCache::~SRVCache()
-{
-    for (size_t i = 0; i < cache.size(); i++)
-    {
-        SafeRelease(cache[i].srv);
-    }
-}
-
-ID3D11ShaderResourceView *TextureStorage11::SRVCache::find(const SRVKey &key) const
-{
-    for (size_t i = 0; i < cache.size(); i++)
-    {
-        if (cache[i].key == key)
-        {
-            return cache[i].srv;
-        }
-    }
-
-    return NULL;
-}
-
-ID3D11ShaderResourceView *TextureStorage11::SRVCache::add(const SRVKey &key, ID3D11ShaderResourceView *srv)
+bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const
 {
-    SRVPair pair = {key, srv};
-    cache.push_back(pair);
-
-    return srv;
+    return std::tie(baseLevel, mipLevels, swizzle) < std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle);
 }
 
-TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
+TextureStorage11::TextureStorage11(Renderer11 *renderer, UINT bindFlags)
     : mBindFlags(bindFlags),
       mTopLevel(0),
       mMipLevels(0),
+      mInternalFormat(GL_NONE),
       mTextureFormat(DXGI_FORMAT_UNKNOWN),
       mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
       mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
@@ -114,6 +88,12 @@ TextureStorage11::~TextureStorage11()
     {
         SafeRelease(mLevelSRVs[level]);
     }
+
+    for (SRVCache::iterator i = mSrvCache.begin(); i != mSrvCache.end(); i++)
+    {
+        SafeRelease(i->second);
+    }
+    mSrvCache.clear();
 }
 
 TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
@@ -183,17 +163,16 @@ int TextureStorage11::getLevelDepth(int mipLevel) const
     return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1);
 }
 
-UINT TextureStorage11::getSubresourceIndex(int mipLevel, int layerTarget) const
+UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const
 {
-    UINT index = 0;
-    if (getResource())
-    {
-        index = D3D11CalcSubresource(mipLevel, layerTarget, mMipLevels);
-    }
-    return index;
+    UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel);
+    UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+    UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
+    ASSERT(subresource != std::numeric_limits<UINT>::max());
+    return subresource;
 }
 
-ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &samplerState)
+gl::Error TextureStorage11::getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV)
 {
     bool swizzleRequired = samplerState.swizzleRequired();
     bool mipmapping = gl::IsMipmapFiltered(samplerState);
@@ -206,38 +185,71 @@ ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &sampl
     {
         verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha);
     }
-    
-    SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired);
-    ID3D11ShaderResourceView *srv = srvCache.find(key);
 
-    if(srv)
+    SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired);
+    SRVCache::const_iterator iter = mSrvCache.find(key);
+    if (iter != mSrvCache.end())
     {
-        return srv;
+        *outSRV = iter->second;
     }
+    else
+    {
+        ID3D11Resource *texture = NULL;
+        if (swizzleRequired)
+        {
+            gl::Error error = getSwizzleTexture(&texture);
+            if (error.isError())
+            {
+                return error;
+            }
+        }
+        else
+        {
+            gl::Error error = getResource(&texture);
+            if (error.isError())
+            {
+                return error;
+            }
+        }
+
+        ID3D11ShaderResourceView *srv = NULL;
+        DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat);
+        gl::Error error = createSRV(samplerState.baseLevel, mipLevels, format, texture, &srv);
+        if (error.isError())
+        {
+            return error;
+        }
 
-    DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat);
-    ID3D11Resource *texture = swizzleRequired ? getSwizzleTexture() : getResource();
+        mSrvCache.insert(std::make_pair(key, srv));
+        *outSRV = srv;
+    }
 
-    srv = createSRV(samplerState.baseLevel, mipLevels, format, texture);
-    
-    return srvCache.add(key, srv);
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11ShaderResourceView *TextureStorage11::getSRVLevel(int mipLevel)
+gl::Error TextureStorage11::getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV)
 {
-    if (mipLevel >= 0 && mipLevel < getLevelCount())
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+    if (!mLevelSRVs[mipLevel])
     {
-        if (!mLevelSRVs[mipLevel])
+        ID3D11Resource *resource = NULL;
+        gl::Error error = getResource(&resource);
+        if (error.isError())
         {
-            mLevelSRVs[mipLevel] = createSRV(mipLevel, 1, mShaderResourceFormat, getResource());
+            return error;
         }
 
-        return mLevelSRVs[mipLevel];
-    }
-    else
-    {
-        return NULL;
+        error = createSRV(mipLevel, 1, mShaderResourceFormat, resource, &mLevelSRVs[mipLevel]);
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    *outSRV = mLevelSRVs[mipLevel];
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
@@ -249,14 +261,25 @@ gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGr
         if (mSwizzleCache[level] != swizzleTarget)
         {
             // Need to re-render the swizzle for this level
-            ID3D11ShaderResourceView *sourceSRV = getSRVLevel(level);
-            ID3D11RenderTargetView *destRTV = getSwizzleRenderTarget(level);
+            ID3D11ShaderResourceView *sourceSRV = NULL;
+            gl::Error error = getSRVLevel(level, &sourceSRV);
+            if (error.isError())
+            {
+                return error;
+            }
+
+            ID3D11RenderTargetView *destRTV = NULL;
+            error = getSwizzleRenderTarget(level, &destRTV);
+            if (error.isError())
+            {
+                return error;
+            }
 
             gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
 
             Blit11 *blitter = mRenderer->getBlitter();
 
-            gl::Error error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
+            error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
             if (error.isError())
             {
                 return error;
@@ -287,104 +310,120 @@ void TextureStorage11::invalidateSwizzleCache()
     }
 }
 
-bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource,
-                                              int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
-                                              GLsizei width, GLsizei height, GLsizei depth)
+gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource,
+                                                   const gl::ImageIndex &index, const gl::Box &copyArea)
 {
-    if (srcTexture)
-    {
-        invalidateSwizzleCacheLevel(level);
+    ASSERT(srcTexture);
 
-        gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
-        gl::Box copyArea(xoffset, yoffset, zoffset, width, height, depth);
+    GLint level = index.mipIndex;
 
-        bool fullCopy = copyArea.x == 0 &&
-                        copyArea.y == 0 &&
-                        copyArea.z == 0 &&
-                        copyArea.width  == texSize.width &&
-                        copyArea.height == texSize.height &&
-                        copyArea.depth  == texSize.depth;
+    invalidateSwizzleCacheLevel(level);
 
-        ID3D11Resource *dstTexture = getResource();
-        unsigned int dstSubresource = getSubresourceIndex(level + mTopLevel, layerTarget);
+    gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
 
-        ASSERT(dstTexture);
+    bool fullCopy = copyArea.x == 0 &&
+                    copyArea.y == 0 &&
+                    copyArea.z == 0 &&
+                    copyArea.width  == texSize.width &&
+                    copyArea.height == texSize.height &&
+                    copyArea.depth  == texSize.depth;
 
-        const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
-        if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0))
-        {
-            // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead
-            Blit11 *blitter = mRenderer->getBlitter();
+    ID3D11Resource *dstTexture = NULL;
+    gl::Error error = getResource(&dstTexture);
+    if (error.isError())
+    {
+        return error;
+    }
 
-            return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize,
-                                             dstTexture, dstSubresource, copyArea, texSize,
-                                             NULL);
-        }
-        else
-        {
-            const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
+    unsigned int dstSubresource = getSubresourceIndex(index);
 
-            D3D11_BOX srcBox;
-            srcBox.left = copyArea.x;
-            srcBox.top = copyArea.y;
-            srcBox.right = copyArea.x + roundUp((unsigned int)width, dxgiFormatInfo.blockWidth);
-            srcBox.bottom = copyArea.y + roundUp((unsigned int)height, dxgiFormatInfo.blockHeight);
-            srcBox.front = copyArea.z;
-            srcBox.back = copyArea.z + copyArea.depth;
+    ASSERT(dstTexture);
 
-            ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+    const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
+    if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0))
+    {
+        // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead
+        Blit11 *blitter = mRenderer->getBlitter();
 
-            context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z,
-                                           srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox);
-            return true;
-        }
+        return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize,
+                                         dstTexture, dstSubresource, copyArea, texSize,
+                                         NULL);
     }
+    else
+    {
+        const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
 
-    return false;
+        D3D11_BOX srcBox;
+        srcBox.left = copyArea.x;
+        srcBox.top = copyArea.y;
+        srcBox.right = copyArea.x + roundUp(static_cast<UINT>(copyArea.width), dxgiFormatInfo.blockWidth);
+        srcBox.bottom = copyArea.y + roundUp(static_cast<UINT>(copyArea.height), dxgiFormatInfo.blockHeight);
+        srcBox.front = copyArea.z;
+        srcBox.back = copyArea.z + copyArea.depth;
+
+        ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+        context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z,
+                                       srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox);
+        return gl::Error(GL_NO_ERROR);
+    }
 }
 
-bool TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource,
-                                            int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
-                                            GLsizei width, GLsizei height, GLsizei depth)
+gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource,
+                                                 const gl::ImageIndex &index, const gl::Box &region)
 {
-    if (dstTexture)
+    ASSERT(dstTexture);
+
+    ID3D11Resource *srcTexture = NULL;
+    gl::Error error = getResource(&srcTexture);
+    if (error.isError())
     {
-        ID3D11Resource *srcTexture = getResource();
-        unsigned int srcSubresource = getSubresourceIndex(level + mTopLevel, layerTarget);
+        return error;
+    }
 
-        ASSERT(srcTexture);
+    ASSERT(srcTexture);
 
-        ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+    unsigned int srcSubresource = getSubresourceIndex(index);
 
-        context->CopySubresourceRegion(dstTexture, dstSubresource, xoffset, yoffset, zoffset,
-                                       srcTexture, srcSubresource, NULL);
-        return true;
-    }
+    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+    context->CopySubresourceRegion(dstTexture, dstSubresource, region.x, region.y, region.z,
+                                   srcTexture, srcSubresource, NULL);
 
-    return false;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
+gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
 {
-    if (source && dest)
+    ASSERT(sourceIndex.layerIndex == destIndex.layerIndex);
+
+    invalidateSwizzleCacheLevel(destIndex.mipIndex);
+
+    RenderTarget *source = NULL;
+    gl::Error error = getRenderTarget(sourceIndex, &source);
+    if (error.isError())
     {
-        ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
-        ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
+        return error;
+    }
 
-        if (sourceSRV && destRTV)
-        {
-            gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth());
-            gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth());
+    RenderTarget *dest = NULL;
+    error = getRenderTarget(destIndex, &dest);
+    if (error.isError())
+    {
+        return error;
+    }
 
-            gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth());
-            gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth());
+    ID3D11ShaderResourceView *sourceSRV = RenderTarget11::makeRenderTarget11(source)->getShaderResourceView();
+    ID3D11RenderTargetView *destRTV = RenderTarget11::makeRenderTarget11(dest)->getRenderTargetView();
 
-            Blit11 *blitter = mRenderer->getBlitter();
+    gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth());
+    gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth());
 
-            blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL,
-                                 gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR);
-        }
-    }
+    gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth());
+    gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth());
+
+    Blit11 *blitter = mRenderer->getBlitter();
+    return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL,
+                                gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR);
 }
 
 void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
@@ -396,7 +435,112 @@ void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGree
     }
 }
 
-TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
+gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage)
+{
+    ASSERT(destStorage);
+
+    ID3D11Resource *sourceResouce = NULL;
+    gl::Error error = getResource(&sourceResouce);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    TextureStorage11 *dest11 = TextureStorage11::makeTextureStorage11(destStorage);
+    ID3D11Resource *destResource = NULL;
+    error = dest11->getResource(&destResource);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+    immediateContext->CopyResource(destResource, sourceResouce);
+
+    dest11->invalidateSwizzleCache();
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type,
+                                    const gl::PixelUnpackState &unpack, const uint8_t *pixelData)
+{
+    ID3D11Resource *resource = NULL;
+    gl::Error error = getResource(&resource);
+    if (error.isError())
+    {
+        return error;
+    }
+    ASSERT(resource);
+
+    UINT destSubresource = getSubresourceIndex(index);
+
+    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(image->getInternalFormat());
+
+    bool fullUpdate = (destBox == NULL || *destBox == gl::Box(0, 0, 0, mTextureWidth, mTextureHeight, mTextureDepth));
+    ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate);
+
+    // TODO(jmadill): Handle compressed formats
+    // Compressed formats have different load syntax, so we'll have to handle them with slightly
+    // different logic. Will implemnent this in a follow-up patch, and ensure we do not use SetData
+    // with compressed formats in the calling logic.
+    ASSERT(!internalFormatInfo.compressed);
+
+    int width = destBox ? destBox->width : static_cast<int>(image->getWidth());
+    int height = destBox ? destBox->height : static_cast<int>(image->getHeight());
+    int depth = destBox ? destBox->depth : static_cast<int>(image->getDepth());
+    UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment);
+    UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment);
+
+    const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat());
+    const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat);
+
+    size_t outputPixelSize = dxgiFormatInfo.pixelBytes;
+
+    UINT bufferRowPitch = outputPixelSize * width;
+    UINT bufferDepthPitch = bufferRowPitch * height;
+
+    MemoryBuffer conversionBuffer;
+    if (!conversionBuffer.resize(bufferDepthPitch * depth))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer.");
+    }
+
+    // TODO: fast path
+    LoadImageFunction loadFunction = d3d11Format.loadFunctions.at(type);
+    loadFunction(width, height, depth,
+                 pixelData, srcRowPitch, srcDepthPitch,
+                 conversionBuffer.data(), bufferRowPitch, bufferDepthPitch);
+
+    ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+
+    if (!fullUpdate)
+    {
+        ASSERT(destBox);
+
+        D3D11_BOX destD3DBox;
+        destD3DBox.left = destBox->x;
+        destD3DBox.right = destBox->x + destBox->width;
+        destD3DBox.top = destBox->y;
+        destD3DBox.bottom = destBox->y + destBox->height;
+        destD3DBox.front = 0;
+        destD3DBox.back = 1;
+
+        immediateContext->UpdateSubresource(resource, destSubresource,
+                                            &destD3DBox, conversionBuffer.data(),
+                                            bufferRowPitch, bufferDepthPitch);
+    }
+    else
+    {
+        immediateContext->UpdateSubresource(resource, destSubresource,
+                                            NULL, conversionBuffer.data(),
+                                            bufferRowPitch, bufferDepthPitch);
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain)
     : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE),
       mTexture(swapchain->getOffscreenTexture()),
       mSwizzleTexture(NULL)
@@ -418,6 +562,8 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch
     mTextureHeight = texDesc.Height;
     mTextureDepth = 1;
 
+    mInternalFormat = swapchain->GetBackBufferInternalFormat();
+
     ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource();
     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
     srv->GetDesc(&srvDesc);
@@ -439,7 +585,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch
     initializeSerials(1, 1);
 }
 
-TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
+TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
     : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)),
       mTexture(NULL),
       mSwizzleTexture(NULL)
@@ -451,6 +597,8 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform
         mSwizzleRenderTargets[i] = NULL;
     }
 
+    mInternalFormat = internalformat;
+
     const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
     mTextureFormat = formatInfo.texFormat;
     mShaderResourceFormat = formatInfo.srvFormat;
@@ -460,51 +608,11 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform
     mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
     mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
 
-    // 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
-    if (width > 0 && height > 0)
-    {
-        // adjust size if needed for compressed textures
-        d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
-
-        ID3D11Device *device = mRenderer->getDevice();
-
-        D3D11_TEXTURE2D_DESC desc;
-        desc.Width = width;      // Compressed texture size constraints?
-        desc.Height = height;
-        desc.MipLevels = desc.MipLevels = mRenderer->isLevel9() ? 1 : ((levels > 0) ? (mTopLevel + levels) : 0);
-        desc.ArraySize = 1;
-        desc.Format = mTextureFormat;
-        desc.SampleDesc.Count = 1;
-        desc.SampleDesc.Quality = 0;
-        desc.Usage = D3D11_USAGE_DEFAULT;
-        desc.BindFlags = getBindFlags();
-        desc.CPUAccessFlags = 0;
-        desc.MiscFlags = 0;
-
-        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
-
-        // this can happen from windows TDR
-        if (d3d11::isDeviceLostError(result))
-        {
-            mRenderer->notifyDeviceLost();
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-        else if (FAILED(result))
-        {
-            ASSERT(result == E_OUTOFMEMORY);
-            ERR("Creating image failed.");
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-        else
-        {
-            mTexture->GetDesc(&desc);
-            mMipLevels = desc.MipLevels;
-            mTextureWidth = desc.Width;
-            mTextureHeight = desc.Height;
-            mTextureDepth = 1;
-        }
-    }
+    d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
+    mMipLevels = mTopLevel + levels;
+    mTextureWidth = width;
+    mTextureHeight = height;
+    mTextureDepth = 1;
 
     initializeSerials(getLevelCount(), 1);
 }
@@ -521,7 +629,11 @@ TextureStorage11_2D::~TextureStorage11_2D()
             if (imageAssociationCorrect)
             {
                 // We must let the Images recover their data before we delete it from the TextureStorage.
-                mAssociatedImages[i]->recoverFromAssociatedStorage();
+                gl::Error error = mAssociatedImages[i]->recoverFromAssociatedStorage();
+                if (error.isError())
+                {
+                    // TODO: Find a way to report this back to the context
+                }
             }
         }
     }
@@ -542,8 +654,10 @@ TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage
     return static_cast<TextureStorage11_2D*>(storage);
 }
 
-void TextureStorage11_2D::associateImage(Image11* image, int level, int layerTarget)
+void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &index)
 {
+    GLint level = index.mipIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -552,8 +666,10 @@ void TextureStorage11_2D::associateImage(Image11* image, int level, int layerTar
     }
 }
 
-bool TextureStorage11_2D::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
+bool TextureStorage11_2D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
     {
         // This validation check should never return false. It means the Image/TextureStorage association is broken.
@@ -566,8 +682,10 @@ bool TextureStorage11_2D::isAssociatedImageValid(int level, int layerTarget, Ima
 }
 
 // disassociateImage allows an Image to end its association with a Storage.
-void TextureStorage11_2D::disassociateImage(int level, int layerTarget, Image11* expectedImage)
+void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -582,8 +700,10 @@ void TextureStorage11_2D::disassociateImage(int level, int layerTarget, Image11*
 }
 
 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
-void TextureStorage11_2D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
+gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage)
 {
+    GLint level = index.mipIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -599,140 +719,171 @@ void TextureStorage11_2D::releaseAssociatedImage(int level, int layerTarget, Ima
             {
                 // Force the image to recover from storage before its data is overwritten.
                 // This will reset mAssociatedImages[level] to NULL too.
-                mAssociatedImages[level]->recoverFromAssociatedStorage();
+                gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage();
+                if (error.isError())
+                {
+                    return error;
+                }
             }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11Resource *TextureStorage11_2D::getResource() const
+gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource)
 {
-    return mTexture;
+    // 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
+    if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
+    {
+        ASSERT(mMipLevels > 0);
+
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width = mTextureWidth;      // Compressed texture size constraints?
+        desc.Height = mTextureHeight;
+        desc.MipLevels = mRenderer->isLevel9() ? 1 : mMipLevels;
+        desc.ArraySize = 1;
+        desc.Format = mTextureFormat;
+        desc.SampleDesc.Count = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage = D3D11_USAGE_DEFAULT;
+        desc.BindFlags = getBindFlags();
+        desc.CPUAccessFlags = 0;
+        desc.MiscFlags = 0;
+
+        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
+
+        // this can happen from windows TDR
+        if (d3d11::isDeviceLostError(result))
+        {
+            mRenderer->notifyDeviceLost();
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result);
+        }
+        else if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result);
+        }
+    }
+
+    *outResource = mTexture;
+    return gl::Error(GL_NO_ERROR);
 }
 
-RenderTarget *TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index)
+gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
 {
     ASSERT(!index.hasLayer());
 
     int level = index.mipIndex;
+    ASSERT(level >= 0 && level < getLevelCount());
 
-    if (level >= 0 && level < getLevelCount())
+    if (!mRenderTarget[level])
     {
-        if (!mRenderTarget[level])
+        ID3D11Resource *texture = NULL;
+        gl::Error error = getResource(&texture);
+        if (error.isError())
         {
-            ID3D11ShaderResourceView *srv = getSRVLevel(level);
-            if (!srv)
-            {
-                return NULL;
-            }
-
-            if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
-            {
-                ID3D11Device *device = mRenderer->getDevice();
+            return error;
+        }
 
-                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-                rtvDesc.Format = mRenderTargetFormat;
-                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
-                rtvDesc.Texture2D.MipSlice = mTopLevel + level;
+        ID3D11ShaderResourceView *srv = NULL;
+        error = getSRVLevel(level, &srv);
+        if (error.isError())
+        {
+            return error;
+        }
 
-                ID3D11RenderTargetView *rtv;
-                HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
+        if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
+        {
+            ID3D11Device *device = mRenderer->getDevice();
 
-                if (result == E_OUTOFMEMORY)
-                {
-                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-                }
-                ASSERT(SUCCEEDED(result));
+            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+            rtvDesc.Format = mRenderTargetFormat;
+            rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+            rtvDesc.Texture2D.MipSlice = mTopLevel + level;
 
-                mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
+            ID3D11RenderTargetView *rtv;
+            HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
 
-                // RenderTarget will take ownership of these resources
-                SafeRelease(rtv);
-            }
-            else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
+            ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+            if (FAILED(result))
             {
-                ID3D11Device *device = mRenderer->getDevice();
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
+            }
 
-                D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
-                dsvDesc.Format = mDepthStencilFormat;
-                dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
-                dsvDesc.Texture2D.MipSlice = mTopLevel + level;
-                dsvDesc.Flags = 0;
+            mRenderTarget[level] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0);
 
-                ID3D11DepthStencilView *dsv;
-                HRESULT result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
+            // RenderTarget will take ownership of these resources
+            SafeRelease(rtv);
+        }
+        else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
+        {
+            ID3D11Device *device = mRenderer->getDevice();
 
-                if (result == E_OUTOFMEMORY)
-                {
-                    SafeRelease(srv);
-                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-                }
-                ASSERT(SUCCEEDED(result));
+            D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+            dsvDesc.Format = mDepthStencilFormat;
+            dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+            dsvDesc.Texture2D.MipSlice = mTopLevel + level;
+            dsvDesc.Flags = 0;
 
-                mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
+            ID3D11DepthStencilView *dsv;
+            HRESULT result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv);
 
-                // RenderTarget will take ownership of these resources
-                SafeRelease(dsv);
-            }
-            else
+            ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+            if (FAILED(result))
             {
-                UNREACHABLE();
+                return gl::Error(GL_OUT_OF_MEMORY,"Failed to create internal depth stencil view for texture storage, result: 0x%X.", result);
             }
-        }
 
-        return mRenderTarget[level];
-    }
-    else
-    {
-        return NULL;
+            mRenderTarget[level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0);
+
+            // RenderTarget will take ownership of these resources
+            SafeRelease(dsv);
+        }
+        else
+        {
+            UNREACHABLE();
+        }
     }
+
+    ASSERT(outRT);
+    *outRT = mRenderTarget[level];
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11ShaderResourceView *TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
+gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+                                         ID3D11ShaderResourceView **outSRV) const
 {
+    ASSERT(outSRV);
+
     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
     srvDesc.Format = format;
     srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
     srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
-    srvDesc.Texture2D.MipLevels = mipLevels;
-
-    ID3D11ShaderResourceView *SRV = NULL;
+    srvDesc.Texture2D.MipLevels = mRenderer->isLevel9() ? -1 : mipLevels;
 
     ID3D11Device *device = mRenderer->getDevice();
-    HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
+    HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
 
-    if (result == E_OUTOFMEMORY)
+    ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+    if (FAILED(result))
     {
-        gl::error(GL_OUT_OF_MEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result);
     }
-    ASSERT(SUCCEEDED(result));
 
-    return SRV;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureStorage11_2D::generateMipmaps()
+gl::Error TextureStorage11_2D::getSwizzleTexture(ID3D11Resource **outTexture)
 {
-    // Base level must already be defined
+    ASSERT(outTexture);
 
-    for (int level = 1; level < getLevelCount(); level++)
+    if (!mSwizzleTexture)
     {
-        invalidateSwizzleCacheLevel(level);
-
-        gl::ImageIndex srcIndex = gl::ImageIndex::Make2D(level - 1);
-        gl::ImageIndex destIndex = gl::ImageIndex::Make2D(level);
-
-        RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex));
-        RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex));
-
-        generateMipmapLayer(source, dest);
-    }
-}
-
-ID3D11Resource *TextureStorage11_2D::getSwizzleTexture()
-{
-    if (!mSwizzleTexture)
-    {
-        ID3D11Device *device = mRenderer->getDevice();
+        ID3D11Device *device = mRenderer->getDevice();
 
         D3D11_TEXTURE2D_DESC desc;
         desc.Width = mTextureWidth;
@@ -749,52 +900,52 @@ ID3D11Resource *TextureStorage11_2D::getSwizzleTexture()
 
         HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
 
-        if (result == E_OUTOFMEMORY)
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
         {
-            return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL));
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result);
         }
-        ASSERT(SUCCEEDED(result));
     }
 
-    return mSwizzleTexture;
+    *outTexture = mSwizzleTexture;
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11RenderTargetView *TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel)
+gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV)
 {
-    if (mipLevel >= 0 && mipLevel < getLevelCount())
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+    ASSERT(outRTV);
+
+    if (!mSwizzleRenderTargets[mipLevel])
     {
-        if (!mSwizzleRenderTargets[mipLevel])
+        ID3D11Resource *swizzleTexture = NULL;
+        gl::Error error = getSwizzleTexture(&swizzleTexture);
+        if (error.isError())
         {
-            ID3D11Resource *swizzleTexture = getSwizzleTexture();
-            if (!swizzleTexture)
-            {
-                return NULL;
-            }
+            return error;
+        }
 
-            ID3D11Device *device = mRenderer->getDevice();
+        ID3D11Device *device = mRenderer->getDevice();
 
-            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-            rtvDesc.Format = mSwizzleRenderTargetFormat;
-            rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
-            rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
+        D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+        rtvDesc.Format = mSwizzleRenderTargetFormat;
+        rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+        rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
 
-            HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
-            if (result == E_OUTOFMEMORY)
-            {
-                return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
-            }
-            ASSERT(SUCCEEDED(result));
-        }
+        HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
 
-        return mSwizzleRenderTargets[mipLevel];
-    }
-    else
-    {
-        return NULL;
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result);
+        }
     }
+
+    *outRTV = mSwizzleRenderTargets[mipLevel];
+    return gl::Error(GL_NO_ERROR);
 }
 
-TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
+TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
     : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
 {
     mTexture = NULL;
@@ -803,13 +954,15 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal
     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
     {
         mSwizzleRenderTargets[level] = NULL;
-        for (unsigned int face = 0; face < 6; face++)
+        for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
         {
             mAssociatedImages[face][level] = NULL;
             mRenderTarget[face][level] = NULL;
         }
     }
 
+    mInternalFormat = internalformat;
+
     const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
     mTextureFormat = formatInfo.texFormat;
     mShaderResourceFormat = formatInfo.srvFormat;
@@ -819,56 +972,23 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal
     mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
     mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
 
-    // if the size is not positive this should be treated as an incomplete texture
-    // we handle that here by skipping the d3d texture creation
-    if (size > 0)
-    {
-        // adjust size if needed for compressed textures
-        int height = size;
-        d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel);
-
-        ID3D11Device *device = mRenderer->getDevice();
+    // adjust size if needed for compressed textures
+    int height = size;
+    d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel);
 
-        D3D11_TEXTURE2D_DESC desc;
-        desc.Width = size;
-        desc.Height = size;
-        desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
-        desc.ArraySize = 6;
-        desc.Format = mTextureFormat;
-        desc.SampleDesc.Count = 1;
-        desc.SampleDesc.Quality = 0;
-        desc.Usage = D3D11_USAGE_DEFAULT;
-        desc.BindFlags = getBindFlags();
-        desc.CPUAccessFlags = 0;
-        desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
-
-        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
-
-        if (FAILED(result))
-        {
-            ASSERT(result == E_OUTOFMEMORY);
-            ERR("Creating image failed.");
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-        else
-        {
-            mTexture->GetDesc(&desc);
-            mMipLevels = desc.MipLevels;
-            mTextureWidth = desc.Width;
-            mTextureHeight = desc.Height;
-            mTextureDepth = 1;
-        }
-    }
+    mMipLevels = mTopLevel + levels;
+    mTextureWidth = size;
+    mTextureHeight = size;
+    mTextureDepth = 1;
 
-    initializeSerials(getLevelCount() * 6, 6);
+    initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT);
 }
 
-
 TextureStorage11_Cube::~TextureStorage11_Cube()
 {
     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
     {
-        for (unsigned int face = 0; face < 6; face++)
+        for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
         {
             if (mAssociatedImages[face][level] != NULL)
             {
@@ -890,7 +1010,7 @@ TextureStorage11_Cube::~TextureStorage11_Cube()
     for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
     {
         SafeRelease(mSwizzleRenderTargets[level]);
-        for (unsigned int face = 0; face < 6; face++)
+        for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
         {
             SafeDelete(mRenderTarget[face][level]);
         }
@@ -903,25 +1023,31 @@ TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureS
     return static_cast<TextureStorage11_Cube*>(storage);
 }
 
-void TextureStorage11_Cube::associateImage(Image11* image, int level, int layerTarget)
+void TextureStorage11_Cube::associateImage(Image11* image, const gl::ImageIndex &index)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
-    ASSERT(0 <= layerTarget && layerTarget < 6);
+    ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT);
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
     {
-        if (0 <= layerTarget && layerTarget < 6)
+        if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT)
         {
             mAssociatedImages[layerTarget][level] = image;
         }
     }
 }
 
-bool TextureStorage11_Cube::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
+bool TextureStorage11_Cube::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
     {
-        if (0 <= layerTarget && layerTarget < 6)
+        if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT)
         {
             // This validation check should never return false. It means the Image/TextureStorage association is broken.
             bool retValue = (mAssociatedImages[layerTarget][level] == expectedImage);
@@ -934,14 +1060,17 @@ bool TextureStorage11_Cube::isAssociatedImageValid(int level, int layerTarget, I
 }
 
 // disassociateImage allows an Image to end its association with a Storage.
-void TextureStorage11_Cube::disassociateImage(int level, int layerTarget, Image11* expectedImage)
+void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
-    ASSERT(0 <= layerTarget && layerTarget < 6);
+    ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT);
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
     {
-        if (0 <= layerTarget && layerTarget < 6)
+        if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT)
         {
             ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
 
@@ -954,14 +1083,17 @@ void TextureStorage11_Cube::disassociateImage(int level, int layerTarget, Image1
 }
 
 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
-void TextureStorage11_Cube::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
+gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
-    ASSERT(0 <= layerTarget && layerTarget < 6);
+    ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT);
 
     if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
     {
-        if (0 <= layerTarget && layerTarget < 6)
+        if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT)
         {
             // No need to let the old Image recover its data, if it is also the incoming Image.
             if (mAssociatedImages[layerTarget][level] != NULL && mAssociatedImages[layerTarget][level] != incomingImage)
@@ -974,114 +1106,165 @@ void TextureStorage11_Cube::releaseAssociatedImage(int level, int layerTarget, I
                 {
                     // Force the image to recover from storage before its data is overwritten.
                     // This will reset mAssociatedImages[level] to NULL too.
-                    mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage();
+                    gl::Error error = mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage();
+                    if (error.isError())
+                    {
+                        return error;
+                    }
                 }
             }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11Resource *TextureStorage11_Cube::getResource() const
+gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource)
 {
-    return mTexture;
+    // if the size is not positive this should be treated as an incomplete texture
+    // we handle that here by skipping the d3d texture creation
+    if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
+    {
+        ASSERT(mMipLevels > 0);
+
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width = mTextureWidth;
+        desc.Height = mTextureHeight;
+        desc.MipLevels = mMipLevels;
+        desc.ArraySize = CUBE_FACE_COUNT;
+        desc.Format = mTextureFormat;
+        desc.SampleDesc.Count = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage = D3D11_USAGE_DEFAULT;
+        desc.BindFlags = getBindFlags();
+        desc.CPUAccessFlags = 0;
+        desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
+
+        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
+
+        // this can happen from windows TDR
+        if (d3d11::isDeviceLostError(result))
+        {
+            mRenderer->notifyDeviceLost();
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result);
+        }
+        else if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result);
+        }
+    }
+
+    *outResource = mTexture;
+    return gl::Error(GL_NO_ERROR);
 }
 
-RenderTarget *TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index)
+gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
 {
     int faceIndex = index.layerIndex;
     int level = index.mipIndex;
 
-    if (level >= 0 && level < getLevelCount())
-    {
-        if (!mRenderTarget[faceIndex][level])
-        {
-            ID3D11Device *device = mRenderer->getDevice();
-            HRESULT result;
+    ASSERT(level >= 0 && level < getLevelCount());
+    ASSERT(faceIndex >= 0 && faceIndex < CUBE_FACE_COUNT);
 
-            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
-            srvDesc.Format = mShaderResourceFormat;
-            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube
-            srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
-            srvDesc.Texture2DArray.MipLevels = 1;
-            srvDesc.Texture2DArray.FirstArraySlice = faceIndex;
-            srvDesc.Texture2DArray.ArraySize = 1;
+    if (!mRenderTarget[faceIndex][level])
+    {
+        ID3D11Device *device = mRenderer->getDevice();
+        HRESULT result;
 
-            ID3D11ShaderResourceView *srv;
-            result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
+        ID3D11Resource *texture = NULL;
+        gl::Error error = getResource(&texture);
+        if (error.isError())
+        {
+            return error;
+        }
 
-            if (result == E_OUTOFMEMORY)
-            {
-                return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-            }
-            ASSERT(SUCCEEDED(result));
+        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+        srvDesc.Format = mShaderResourceFormat;
+        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube
+        srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
+        srvDesc.Texture2DArray.MipLevels = 1;
+        srvDesc.Texture2DArray.FirstArraySlice = faceIndex;
+        srvDesc.Texture2DArray.ArraySize = 1;
 
-            if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
-            {
-                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-                rtvDesc.Format = mRenderTargetFormat;
-                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
-                rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
-                rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
-                rtvDesc.Texture2DArray.ArraySize = 1;
+        ID3D11ShaderResourceView *srv;
+        result = device->CreateShaderResourceView(texture, &srvDesc, &srv);
 
-                ID3D11RenderTargetView *rtv;
-                result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result);
+        }
 
-                if (result == E_OUTOFMEMORY)
-                {
-                    SafeRelease(srv);
-                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-                }
-                ASSERT(SUCCEEDED(result));
+        if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
+        {
+            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+            rtvDesc.Format = mRenderTargetFormat;
+            rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+            rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
+            rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
+            rtvDesc.Texture2DArray.ArraySize = 1;
 
-                mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
+            ID3D11RenderTargetView *rtv;
+            result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
 
-                // RenderTarget will take ownership of these resources
-                SafeRelease(rtv);
+            ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+            if (FAILED(result))
+            {
                 SafeRelease(srv);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
             }
-            else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
-            {
-                D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
-                dsvDesc.Format = mDepthStencilFormat;
-                dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
-                dsvDesc.Flags = 0;
-                dsvDesc.Texture2DArray.MipSlice = mTopLevel + level;
-                dsvDesc.Texture2DArray.FirstArraySlice = faceIndex;
-                dsvDesc.Texture2DArray.ArraySize = 1;
-
-                ID3D11DepthStencilView *dsv;
-                result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
-
-                if (result == E_OUTOFMEMORY)
-                {
-                    SafeRelease(srv);
-                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-                }
-                ASSERT(SUCCEEDED(result));
 
-                mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
+            mRenderTarget[faceIndex][level] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0);
 
-                // RenderTarget will take ownership of these resources
-                SafeRelease(dsv);
-                SafeRelease(srv);
-            }
-            else
+            // RenderTarget will take ownership of these resources
+            SafeRelease(rtv);
+            SafeRelease(srv);
+        }
+        else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
+        {
+            D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+            dsvDesc.Format = mDepthStencilFormat;
+            dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+            dsvDesc.Flags = 0;
+            dsvDesc.Texture2DArray.MipSlice = mTopLevel + level;
+            dsvDesc.Texture2DArray.FirstArraySlice = faceIndex;
+            dsvDesc.Texture2DArray.ArraySize = 1;
+
+            ID3D11DepthStencilView *dsv;
+            result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv);
+
+            ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+            if (FAILED(result))
             {
-                UNREACHABLE();
+                SafeRelease(srv);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal depth stencil view for texture storage, result: 0x%X.", result);
             }
-        }
 
-        return mRenderTarget[faceIndex][level];
-    }
-    else
-    {
-        return NULL;
+            mRenderTarget[faceIndex][level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0);
+
+            // RenderTarget will take ownership of these resources
+            SafeRelease(dsv);
+            SafeRelease(srv);
+        }
+        else
+        {
+            UNREACHABLE();
+        }
     }
+
+    ASSERT(outRT);
+    *outRT = mRenderTarget[faceIndex][level];
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
+gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+                                           ID3D11ShaderResourceView **outSRV) const
 {
+    ASSERT(outSRV);
+
     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
     srvDesc.Format = format;
 
@@ -1093,7 +1276,7 @@ ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mi
         srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
         srvDesc.Texture2DArray.MipLevels = 1;
         srvDesc.Texture2DArray.FirstArraySlice = 0;
-        srvDesc.Texture2DArray.ArraySize = 6;
+        srvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT;
     }
     else
     {
@@ -1102,43 +1285,22 @@ ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mi
         srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
     }
 
-    ID3D11ShaderResourceView *SRV = NULL;
-
     ID3D11Device *device = mRenderer->getDevice();
-    HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
+    HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
 
-    if (result == E_OUTOFMEMORY)
+    ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+    if (FAILED(result))
     {
-        gl::error(GL_OUT_OF_MEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result);
     }
-    ASSERT(SUCCEEDED(result));
 
-    return SRV;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureStorage11_Cube::generateMipmaps()
+gl::Error TextureStorage11_Cube::getSwizzleTexture(ID3D11Resource **outTexture)
 {
-    // Base level must already be defined
-
-    for (int faceIndex = 0; faceIndex < 6; faceIndex++)
-    {
-        for (int level = 1; level < getLevelCount(); level++)
-        {
-            invalidateSwizzleCacheLevel(level);
-
-            gl::ImageIndex srcIndex = gl::ImageIndex::MakeCube(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1);
-            gl::ImageIndex destIndex = gl::ImageIndex::MakeCube(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level);
-
-            RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex));
-            RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex));
+    ASSERT(outTexture);
 
-            generateMipmapLayer(source, dest);
-        }
-    }
-}
-
-ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture()
-{
     if (!mSwizzleTexture)
     {
         ID3D11Device *device = mRenderer->getDevice();
@@ -1147,7 +1309,7 @@ ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture()
         desc.Width = mTextureWidth;
         desc.Height = mTextureHeight;
         desc.MipLevels = mMipLevels;
-        desc.ArraySize = 6;
+        desc.ArraySize = CUBE_FACE_COUNT;
         desc.Format = mSwizzleTextureFormat;
         desc.SampleDesc.Count = 1;
         desc.SampleDesc.Quality = 0;
@@ -1158,55 +1320,54 @@ ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture()
 
         HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
 
-        if (result == E_OUTOFMEMORY)
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
         {
-            return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL));
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result);
         }
-        ASSERT(SUCCEEDED(result));
     }
 
-    return mSwizzleTexture;
+    *outTexture = mSwizzleTexture;
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11RenderTargetView *TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel)
+gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV)
 {
-    if (mipLevel >= 0 && mipLevel < getLevelCount())
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+    ASSERT(outRTV);
+
+    if (!mSwizzleRenderTargets[mipLevel])
     {
-        if (!mSwizzleRenderTargets[mipLevel])
+        ID3D11Resource *swizzleTexture = NULL;
+        gl::Error error = getSwizzleTexture(&swizzleTexture);
+        if (error.isError())
         {
-            ID3D11Resource *swizzleTexture = getSwizzleTexture();
-            if (!swizzleTexture)
-            {
-                return NULL;
-            }
+            return error;
+        }
 
-            ID3D11Device *device = mRenderer->getDevice();
+        ID3D11Device *device = mRenderer->getDevice();
 
-            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-            rtvDesc.Format = mSwizzleRenderTargetFormat;
-            rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
-            rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
-            rtvDesc.Texture2DArray.FirstArraySlice = 0;
-            rtvDesc.Texture2DArray.ArraySize = 6;
+        D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+        rtvDesc.Format = mSwizzleRenderTargetFormat;
+        rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+        rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+        rtvDesc.Texture2DArray.FirstArraySlice = 0;
+        rtvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT;
 
-            HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
+        HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
 
-            if (result == E_OUTOFMEMORY)
-            {
-                return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
-            }
-            ASSERT(SUCCEEDED(result));
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result);
         }
-
-        return mSwizzleRenderTargets[mipLevel];
-    }
-    else
-    {
-        return NULL;
     }
+
+    *outRTV = mSwizzleRenderTargets[mipLevel];
+    return gl::Error(GL_NO_ERROR);
 }
 
-TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget,
+TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
                                          GLsizei width, GLsizei height, GLsizei depth, int levels)
     : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
 {
@@ -1220,6 +1381,8 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalform
         mSwizzleRenderTargets[i] = NULL;
     }
 
+    mInternalFormat = internalformat;
+
     const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
     mTextureFormat = formatInfo.texFormat;
     mShaderResourceFormat = formatInfo.srvFormat;
@@ -1229,49 +1392,13 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalform
     mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
     mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
 
-    // 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
-    if (width > 0 && height > 0 && depth > 0)
-    {
-        // adjust size if needed for compressed textures
-        d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
+    // adjust size if needed for compressed textures
+    d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
 
-        ID3D11Device *device = mRenderer->getDevice();
-
-        D3D11_TEXTURE3D_DESC desc;
-        desc.Width = width;
-        desc.Height = height;
-        desc.Depth = depth;
-        desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
-        desc.Format = mTextureFormat;
-        desc.Usage = D3D11_USAGE_DEFAULT;
-        desc.BindFlags = getBindFlags();
-        desc.CPUAccessFlags = 0;
-        desc.MiscFlags = 0;
-
-        HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture);
-
-        // this can happen from windows TDR
-        if (d3d11::isDeviceLostError(result))
-        {
-            mRenderer->notifyDeviceLost();
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-        else if (FAILED(result))
-        {
-            ASSERT(result == E_OUTOFMEMORY);
-            ERR("Creating image failed.");
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-        else
-        {
-            mTexture->GetDesc(&desc);
-            mMipLevels = desc.MipLevels;
-            mTextureWidth = desc.Width;
-            mTextureHeight = desc.Height;
-            mTextureDepth = desc.Depth;
-        }
-    }
+    mMipLevels = mTopLevel + levels;
+    mTextureWidth = width;
+    mTextureHeight = height;
+    mTextureDepth = depth;
 
     initializeSerials(getLevelCount() * depth, depth);
 }
@@ -1315,8 +1442,10 @@ TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage
     return static_cast<TextureStorage11_3D*>(storage);
 }
 
-void TextureStorage11_3D::associateImage(Image11* image, int level, int layerTarget)
+void TextureStorage11_3D::associateImage(Image11* image, const gl::ImageIndex &index)
 {
+    GLint level = index.mipIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -1325,8 +1454,10 @@ void TextureStorage11_3D::associateImage(Image11* image, int level, int layerTar
     }
 }
 
-bool TextureStorage11_3D::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
+bool TextureStorage11_3D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
     {
         // This validation check should never return false. It means the Image/TextureStorage association is broken.
@@ -1339,8 +1470,10 @@ bool TextureStorage11_3D::isAssociatedImageValid(int level, int layerTarget, Ima
 }
 
 // disassociateImage allows an Image to end its association with a Storage.
-void TextureStorage11_3D::disassociateImage(int level, int layerTarget, Image11* expectedImage)
+void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+
     ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -1355,8 +1488,10 @@ void TextureStorage11_3D::disassociateImage(int level, int layerTarget, Image11*
 }
 
 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
-void TextureStorage11_3D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
+gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage)
 {
+    GLint level = index.mipIndex;
+
     ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS));
 
     if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
@@ -1372,148 +1507,188 @@ void TextureStorage11_3D::releaseAssociatedImage(int level, int layerTarget, Ima
             {
                 // Force the image to recover from storage before its data is overwritten.
                 // This will reset mAssociatedImages[level] to NULL too.
-                mAssociatedImages[level]->recoverFromAssociatedStorage();
+                gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage();
+                if (error.isError())
+                {
+                    return error;
+                }
             }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11Resource *TextureStorage11_3D::getResource() const
+gl::Error TextureStorage11_3D::getResource(ID3D11Resource **outResource)
 {
-    return mTexture;
+    // 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
+    if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
+    {
+        ASSERT(mMipLevels > 0);
+
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE3D_DESC desc;
+        desc.Width = mTextureWidth;
+        desc.Height = mTextureHeight;
+        desc.Depth = mTextureDepth;
+        desc.MipLevels = mMipLevels;
+        desc.Format = mTextureFormat;
+        desc.Usage = D3D11_USAGE_DEFAULT;
+        desc.BindFlags = getBindFlags();
+        desc.CPUAccessFlags = 0;
+        desc.MiscFlags = 0;
+
+        HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture);
+
+        // this can happen from windows TDR
+        if (d3d11::isDeviceLostError(result))
+        {
+            mRenderer->notifyDeviceLost();
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result);
+        }
+        else if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result);
+        }
+    }
+
+    *outResource = mTexture;
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11ShaderResourceView *TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
+gl::Error TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+                                         ID3D11ShaderResourceView **outSRV) const
 {
+    ASSERT(outSRV);
+
     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
     srvDesc.Format = format;
     srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
     srvDesc.Texture3D.MostDetailedMip = baseLevel;
     srvDesc.Texture3D.MipLevels = mipLevels;
 
-    ID3D11ShaderResourceView *SRV = NULL;
-
     ID3D11Device *device = mRenderer->getDevice();
-    HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
+    HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
 
-    if (result == E_OUTOFMEMORY)
+    ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+    if (FAILED(result))
     {
-        gl::error(GL_OUT_OF_MEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result);
     }
-    ASSERT(SUCCEEDED(result));
 
-    return SRV;
+    return gl::Error(GL_NO_ERROR);
 }
 
-RenderTarget *TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index)
+gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
 {
     int mipLevel = index.mipIndex;
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
 
-    if (mipLevel >= 0 && mipLevel < getLevelCount())
-    {
-        ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN);
+    ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN);
 
-        if (!index.hasLayer())
+    if (!index.hasLayer())
+    {
+        if (!mLevelRenderTargets[mipLevel])
         {
-            if (!mLevelRenderTargets[mipLevel])
+            ID3D11Resource *texture = NULL;
+            gl::Error error = getResource(&texture);
+            if (error.isError())
             {
-                ID3D11ShaderResourceView *srv = getSRVLevel(mipLevel);
-                if (!srv)
-                {
-                    return NULL;
-                }
-
-                ID3D11Device *device = mRenderer->getDevice();
-
-                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-                rtvDesc.Format = mRenderTargetFormat;
-                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
-                rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
-                rtvDesc.Texture3D.FirstWSlice = 0;
-                rtvDesc.Texture3D.WSize = -1;
-
-                ID3D11RenderTargetView *rtv;
-                HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
+                return error;
+            }
 
-                if (result == E_OUTOFMEMORY)
-                {
-                    SafeRelease(srv);
-                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-                }
-                ASSERT(SUCCEEDED(result));
+            ID3D11ShaderResourceView *srv = NULL;
+            error = getSRVLevel(mipLevel, &srv);
+            if (error.isError())
+            {
+                return error;
+            }
 
-                mLevelRenderTargets[mipLevel] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel));
+            ID3D11Device *device = mRenderer->getDevice();
 
-                // RenderTarget will take ownership of these resources
-                SafeRelease(rtv);
-            }
+            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+            rtvDesc.Format = mRenderTargetFormat;
+            rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+            rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
+            rtvDesc.Texture3D.FirstWSlice = 0;
+            rtvDesc.Texture3D.WSize = -1;
 
-            return mLevelRenderTargets[mipLevel];
-        }
-        else
-        {
-            int layer = index.layerIndex;
+            ID3D11RenderTargetView *rtv;
+            HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
 
-            LevelLayerKey key(mipLevel, layer);
-            if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
+            ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+            if (FAILED(result))
             {
-                ID3D11Device *device = mRenderer->getDevice();
-                HRESULT result;
-
-                // TODO, what kind of SRV is expected here?
-                ID3D11ShaderResourceView *srv = NULL;
+                SafeRelease(srv);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
+            }
 
-                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-                rtvDesc.Format = mRenderTargetFormat;
-                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
-                rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
-                rtvDesc.Texture3D.FirstWSlice = layer;
-                rtvDesc.Texture3D.WSize = 1;
+            mLevelRenderTargets[mipLevel] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel), 0);
 
-                ID3D11RenderTargetView *rtv;
-                result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
+            // RenderTarget will take ownership of these resources
+            SafeRelease(rtv);
+        }
 
-                if (result == E_OUTOFMEMORY)
-                {
-                    SafeRelease(srv);
-                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-                }
-                ASSERT(SUCCEEDED(result));
+        ASSERT(outRT);
+        *outRT = mLevelRenderTargets[mipLevel];
+        return gl::Error(GL_NO_ERROR);
+    }
+    else
+    {
+        int layer = index.layerIndex;
 
-                mLevelLayerRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1);
+        LevelLayerKey key(mipLevel, layer);
+        if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
+        {
+            ID3D11Device *device = mRenderer->getDevice();
+            HRESULT result;
 
-                // RenderTarget will take ownership of these resources
-                SafeRelease(rtv);
-                SafeRelease(srv);
+            ID3D11Resource *texture = NULL;
+            gl::Error error = getResource(&texture);
+            if (error.isError())
+            {
+                return error;
             }
 
-            return mLevelLayerRenderTargets[key];
-        }
-    }
+            // TODO, what kind of SRV is expected here?
+            ID3D11ShaderResourceView *srv = NULL;
 
-    return NULL;
-}
+            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+            rtvDesc.Format = mRenderTargetFormat;
+            rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+            rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
+            rtvDesc.Texture3D.FirstWSlice = layer;
+            rtvDesc.Texture3D.WSize = 1;
 
-void TextureStorage11_3D::generateMipmaps()
-{
-    // Base level must already be defined
+            ID3D11RenderTargetView *rtv;
+            result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
 
-    for (int level = 1; level < getLevelCount(); level++)
-    {
-        invalidateSwizzleCacheLevel(level);
+            ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                SafeRelease(srv); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
+            }
+            ASSERT(SUCCEEDED(result));
 
-        gl::ImageIndex srcIndex = gl::ImageIndex::Make3D(level - 1);
-        gl::ImageIndex destIndex = gl::ImageIndex::Make3D(level);
+            mLevelLayerRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0);
 
-        RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex));
-        RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex));
+            // RenderTarget will take ownership of these resources
+            SafeRelease(rtv);
+        }
 
-        generateMipmapLayer(source, dest);
+        ASSERT(outRT);
+        *outRT = mLevelLayerRenderTargets[key];
+        return gl::Error(GL_NO_ERROR);
     }
 }
 
-ID3D11Resource *TextureStorage11_3D::getSwizzleTexture()
+gl::Error TextureStorage11_3D::getSwizzleTexture(ID3D11Resource **outTexture)
 {
+    ASSERT(outTexture);
+
     if (!mSwizzleTexture)
     {
         ID3D11Device *device = mRenderer->getDevice();
@@ -1531,55 +1706,54 @@ ID3D11Resource *TextureStorage11_3D::getSwizzleTexture()
 
         HRESULT result = device->CreateTexture3D(&desc, NULL, &mSwizzleTexture);
 
-        if (result == E_OUTOFMEMORY)
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
         {
-            return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture3D*>(NULL));
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result);
         }
-        ASSERT(SUCCEEDED(result));
     }
 
-    return mSwizzleTexture;
+    *outTexture = mSwizzleTexture;
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11RenderTargetView *TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel)
+gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV)
 {
-    if (mipLevel >= 0 && mipLevel < getLevelCount())
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+    ASSERT(outRTV);
+
+    if (!mSwizzleRenderTargets[mipLevel])
     {
-        if (!mSwizzleRenderTargets[mipLevel])
+        ID3D11Resource *swizzleTexture = NULL;
+        gl::Error error = getSwizzleTexture(&swizzleTexture);
+        if (error.isError())
         {
-            ID3D11Resource *swizzleTexture = getSwizzleTexture();
-            if (!swizzleTexture)
-            {
-                return NULL;
-            }
+            return error;
+        }
 
-            ID3D11Device *device = mRenderer->getDevice();
+        ID3D11Device *device = mRenderer->getDevice();
 
-            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-            rtvDesc.Format = mSwizzleRenderTargetFormat;
-            rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
-            rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
-            rtvDesc.Texture3D.FirstWSlice = 0;
-            rtvDesc.Texture3D.WSize = -1;
+        D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+        rtvDesc.Format = mSwizzleRenderTargetFormat;
+        rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+        rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
+        rtvDesc.Texture3D.FirstWSlice = 0;
+        rtvDesc.Texture3D.WSize = -1;
 
-            HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
+        HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
 
-            if (result == E_OUTOFMEMORY)
-            {
-                return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
-            }
-            ASSERT(SUCCEEDED(result));
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result);
         }
-
-        return mSwizzleRenderTargets[mipLevel];
-    }
-    else
-    {
-        return NULL;
     }
+
+    *outRTV = mSwizzleRenderTargets[mipLevel];
+    return gl::Error(GL_NO_ERROR);
 }
 
-TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget,
+TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
                                                    GLsizei width, GLsizei height, GLsizei depth, int levels)
     : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
 {
@@ -1591,6 +1765,8 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in
         mSwizzleRenderTargets[level] = NULL;
     }
 
+    mInternalFormat = internalformat;
+
     const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
     mTextureFormat = formatInfo.texFormat;
     mShaderResourceFormat = formatInfo.srvFormat;
@@ -1600,51 +1776,13 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in
     mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
     mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
 
-    // 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
-    if (width > 0 && height > 0 && depth > 0)
-    {
-        // adjust size if needed for compressed textures
-        d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
-
-        ID3D11Device *device = mRenderer->getDevice();
-
-        D3D11_TEXTURE2D_DESC desc;
-        desc.Width = width;
-        desc.Height = height;
-        desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
-        desc.ArraySize = depth;
-        desc.Format = mTextureFormat;
-        desc.SampleDesc.Count = 1;
-        desc.SampleDesc.Quality = 0;
-        desc.Usage = D3D11_USAGE_DEFAULT;
-        desc.BindFlags = getBindFlags();
-        desc.CPUAccessFlags = 0;
-        desc.MiscFlags = 0;
+    // adjust size if needed for compressed textures
+    d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
 
-        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
-
-        // this can happen from windows TDR
-        if (d3d11::isDeviceLostError(result))
-        {
-            mRenderer->notifyDeviceLost();
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-        else if (FAILED(result))
-        {
-            ASSERT(result == E_OUTOFMEMORY);
-            ERR("Creating image failed.");
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-        else
-        {
-            mTexture->GetDesc(&desc);
-            mMipLevels = desc.MipLevels;
-            mTextureWidth = desc.Width;
-            mTextureHeight = desc.Height;
-            mTextureDepth = desc.ArraySize;
-        }
-    }
+    mMipLevels = mTopLevel + levels;
+    mTextureWidth = width;
+    mTextureHeight = height;
+    mTextureDepth = depth;
 
     initializeSerials(getLevelCount() * depth, depth);
 }
@@ -1685,8 +1823,11 @@ TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray
     return static_cast<TextureStorage11_2DArray*>(storage);
 }
 
-void TextureStorage11_2DArray::associateImage(Image11* image, int level, int layerTarget)
+void TextureStorage11_2DArray::associateImage(Image11* image, const gl::ImageIndex &index)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     ASSERT(0 <= level && level < getLevelCount());
 
     if (0 <= level && level < getLevelCount())
@@ -1696,8 +1837,11 @@ void TextureStorage11_2DArray::associateImage(Image11* image, int level, int lay
     }
 }
 
-bool TextureStorage11_2DArray::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage)
+bool TextureStorage11_2DArray::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     LevelLayerKey key(level, layerTarget);
 
     // This validation check should never return false. It means the Image/TextureStorage association is broken.
@@ -1707,8 +1851,11 @@ bool TextureStorage11_2DArray::isAssociatedImageValid(int level, int layerTarget
 }
 
 // disassociateImage allows an Image to end its association with a Storage.
-void TextureStorage11_2DArray::disassociateImage(int level, int layerTarget, Image11* expectedImage)
+void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     LevelLayerKey key(level, layerTarget);
 
     bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage));
@@ -1721,8 +1868,11 @@ void TextureStorage11_2DArray::disassociateImage(int level, int layerTarget, Ima
 }
 
 // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
-void TextureStorage11_2DArray::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage)
+gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage)
 {
+    GLint level = index.mipIndex;
+    GLint layerTarget = index.layerIndex;
+
     LevelLayerKey key(level, layerTarget);
 
     ASSERT(mAssociatedImages.find(key) != mAssociatedImages.end());
@@ -1739,18 +1889,62 @@ void TextureStorage11_2DArray::releaseAssociatedImage(int level, int layerTarget
             {
                 // Force the image to recover from storage before its data is overwritten.
                 // This will reset mAssociatedImages[level] to NULL too.
-                mAssociatedImages[key]->recoverFromAssociatedStorage();
+                gl::Error error = mAssociatedImages[key]->recoverFromAssociatedStorage();
+                if (error.isError())
+                {
+                    return error;
+                }
             }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11Resource *TextureStorage11_2DArray::getResource() const
+gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **outResource)
 {
-    return mTexture;
+    // 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
+    if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
+    {
+        ASSERT(mMipLevels > 0);
+
+        ID3D11Device *device = mRenderer->getDevice();
+
+        D3D11_TEXTURE2D_DESC desc;
+        desc.Width = mTextureWidth;
+        desc.Height = mTextureHeight;
+        desc.MipLevels = mMipLevels;
+        desc.ArraySize = mTextureDepth;
+        desc.Format = mTextureFormat;
+        desc.SampleDesc.Count = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Usage = D3D11_USAGE_DEFAULT;
+        desc.BindFlags = getBindFlags();
+        desc.CPUAccessFlags = 0;
+        desc.MiscFlags = 0;
+
+        HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
+
+        // this can happen from windows TDR
+        if (d3d11::isDeviceLostError(result))
+        {
+            mRenderer->notifyDeviceLost();
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result);
+        }
+        else if (FAILED(result))
+        {
+            ASSERT(result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result);
+        }
+    }
+
+    *outResource = mTexture;
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11ShaderResourceView *TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
+gl::Error TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+                                              ID3D11ShaderResourceView **outSRV) const
 {
     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
     srvDesc.Format = format;
@@ -1760,112 +1954,94 @@ ID3D11ShaderResourceView *TextureStorage11_2DArray::createSRV(int baseLevel, int
     srvDesc.Texture2DArray.FirstArraySlice = 0;
     srvDesc.Texture2DArray.ArraySize = mTextureDepth;
 
-    ID3D11ShaderResourceView *SRV = NULL;
-
     ID3D11Device *device = mRenderer->getDevice();
-    HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
+    HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
 
-    if (result == E_OUTOFMEMORY)
+    ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+    if (FAILED(result))
     {
-        gl::error(GL_OUT_OF_MEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result);
     }
-    ASSERT(SUCCEEDED(result));
 
-    return SRV;
+    return gl::Error(GL_NO_ERROR);
 }
 
-RenderTarget *TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index)
+gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
 {
     ASSERT(index.hasLayer());
 
     int mipLevel = index.mipIndex;
     int layer = index.layerIndex;
 
-    if (mipLevel >= 0 && mipLevel < getLevelCount())
-    {
-        LevelLayerKey key(mipLevel, layer);
-        if (mRenderTargets.find(key) == mRenderTargets.end())
-        {
-            ID3D11Device *device = mRenderer->getDevice();
-            HRESULT result;
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
 
-            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
-            srvDesc.Format = mShaderResourceFormat;
-            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
-            srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel;
-            srvDesc.Texture2DArray.MipLevels = 1;
-            srvDesc.Texture2DArray.FirstArraySlice = layer;
-            srvDesc.Texture2DArray.ArraySize = 1;
+    LevelLayerKey key(mipLevel, layer);
+    if (mRenderTargets.find(key) == mRenderTargets.end())
+    {
+        ID3D11Device *device = mRenderer->getDevice();
+        HRESULT result;
 
-            ID3D11ShaderResourceView *srv;
-            result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
+        ID3D11Resource *texture = NULL;
+        gl::Error error = getResource(&texture);
+        if (error.isError())
+        {
+            return error;
+        }
 
-            if (result == E_OUTOFMEMORY)
-            {
-                return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-            }
-            ASSERT(SUCCEEDED(result));
+        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+        srvDesc.Format = mShaderResourceFormat;
+        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+        srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel;
+        srvDesc.Texture2DArray.MipLevels = 1;
+        srvDesc.Texture2DArray.FirstArraySlice = layer;
+        srvDesc.Texture2DArray.ArraySize = 1;
 
-            if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
-            {
-                D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-                rtvDesc.Format = mRenderTargetFormat;
-                rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
-                rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
-                rtvDesc.Texture2DArray.FirstArraySlice = layer;
-                rtvDesc.Texture2DArray.ArraySize = 1;
+        ID3D11ShaderResourceView *srv;
+        result = device->CreateShaderResourceView(texture, &srvDesc, &srv);
 
-                ID3D11RenderTargetView *rtv;
-                result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result);
+        }
 
-                if (result == E_OUTOFMEMORY)
-                {
-                    SafeRelease(srv);
-                    return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
-                }
-                ASSERT(SUCCEEDED(result));
+        if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
+        {
+            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+            rtvDesc.Format = mRenderTargetFormat;
+            rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+            rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+            rtvDesc.Texture2DArray.FirstArraySlice = layer;
+            rtvDesc.Texture2DArray.ArraySize = 1;
 
-                mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1);
+            ID3D11RenderTargetView *rtv;
+            result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
 
-                // RenderTarget will take ownership of these resources
-                SafeRelease(rtv);
-                SafeRelease(srv);
-            }
-            else
+            ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+            if (FAILED(result))
             {
-                UNREACHABLE();
+                SafeRelease(srv);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
             }
-        }
-
-        return mRenderTargets[key];
-    }
-    else
-    {
-        return NULL;
-    }
-}
 
-void TextureStorage11_2DArray::generateMipmaps()
-{
-    // Base level must already be defined
+            mRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0);
 
-    for (int level = 0; level < getLevelCount(); level++)
-    {
-        invalidateSwizzleCacheLevel(level);
-        for (unsigned int layer = 0; layer < mTextureDepth; layer++)
+            // RenderTarget will take ownership of these resources
+            SafeRelease(rtv);
+            SafeRelease(srv);
+        }
+        else
         {
-            gl::ImageIndex sourceIndex = gl::ImageIndex::Make2DArray(level - 1, layer);
-            gl::ImageIndex destIndex = gl::ImageIndex::Make2DArray(level, layer);
-
-            RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(sourceIndex));
-            RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex));
-
-            generateMipmapLayer(source, dest);
+            UNREACHABLE();
         }
     }
+
+    ASSERT(outRT);
+    *outRT = mRenderTargets[key];
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11Resource *TextureStorage11_2DArray::getSwizzleTexture()
+gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture)
 {
     if (!mSwizzleTexture)
     {
@@ -1886,52 +2062,51 @@ ID3D11Resource *TextureStorage11_2DArray::getSwizzleTexture()
 
         HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
 
-        if (result == E_OUTOFMEMORY)
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
         {
-            return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL));
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result);
         }
-        ASSERT(SUCCEEDED(result));
     }
 
-    return mSwizzleTexture;
+    *outTexture = mSwizzleTexture;
+    return gl::Error(GL_NO_ERROR);
 }
 
-ID3D11RenderTargetView *TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel)
+gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV)
 {
-    if (mipLevel >= 0 && mipLevel < getLevelCount())
+    ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+    ASSERT(outRTV);
+
+    if (!mSwizzleRenderTargets[mipLevel])
     {
-        if (!mSwizzleRenderTargets[mipLevel])
+        ID3D11Resource *swizzleTexture = NULL;
+        gl::Error error = getSwizzleTexture(&swizzleTexture);
+        if (error.isError())
         {
-            ID3D11Resource *swizzleTexture = getSwizzleTexture();
-            if (!swizzleTexture)
-            {
-                return NULL;
-            }
+            return error;
+        }
 
-            ID3D11Device *device = mRenderer->getDevice();
+        ID3D11Device *device = mRenderer->getDevice();
 
-            D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
-            rtvDesc.Format = mSwizzleRenderTargetFormat;
-            rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
-            rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
-            rtvDesc.Texture2DArray.FirstArraySlice = 0;
-            rtvDesc.Texture2DArray.ArraySize = mTextureDepth;
+        D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+        rtvDesc.Format = mSwizzleRenderTargetFormat;
+        rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+        rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+        rtvDesc.Texture2DArray.FirstArraySlice = 0;
+        rtvDesc.Texture2DArray.ArraySize = mTextureDepth;
 
-            HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
+        HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
 
-            if (result == E_OUTOFMEMORY)
-            {
-                return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
-            }
-            ASSERT(SUCCEEDED(result));
+        ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result);
         }
-
-        return mSwizzleRenderTargets[mipLevel];
-    }
-    else
-    {
-        return NULL;
     }
+
+    *outRTV = mSwizzleRenderTargets[mipLevel];
+    return gl::Error(GL_NO_ERROR);
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h
index 9d63b2699de..930300a63de 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h
@@ -25,7 +25,6 @@ namespace rx
 {
 class RenderTarget;
 class RenderTarget11;
-class Renderer;
 class Renderer11;
 class SwapChain11;
 class Image11;
@@ -41,47 +40,49 @@ class TextureStorage11 : public TextureStorage
 
     UINT getBindFlags() const;
 
-    virtual ID3D11Resource *getResource() const = 0;
-    virtual ID3D11ShaderResourceView *getSRV(const gl::SamplerState &samplerState);
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0;
+    virtual gl::Error getResource(ID3D11Resource **outResource) = 0;
+    virtual gl::Error getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV);
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0;
 
-    virtual void generateMipmaps() = 0;
+    virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
 
     virtual int getTopLevel() const;
     virtual bool isRenderTarget() const;
     virtual bool isManaged() const;
     virtual int getLevelCount() const;
-    UINT getSubresourceIndex(int mipLevel, int layerTarget) const;
+    UINT getSubresourceIndex(const gl::ImageIndex &index) const;
 
     gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
     void invalidateSwizzleCacheLevel(int mipLevel);
     void invalidateSwizzleCache();
 
-    bool updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource, int level,
-                                int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
-                                GLsizei width, GLsizei height, GLsizei depth);
+    gl::Error updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource,
+                                     const gl::ImageIndex &index, const gl::Box &copyArea);
 
-    bool copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, int level,
-                              int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
-                              GLsizei width, GLsizei height, GLsizei depth);
+    gl::Error copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource,
+                                   const gl::ImageIndex &index, const gl::Box &region);
 
-    virtual void associateImage(Image11* image, int level, int layerTarget) = 0;
-    virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage) = 0;
-    virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) = 0;
-    virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) = 0;
+    virtual void associateImage(Image11* image, const gl::ImageIndex &index) = 0;
+    virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) = 0;
+    virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) = 0;
+    virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0;
+
+    virtual gl::Error copyToStorage(TextureStorage *destStorage);
+    virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type,
+                              const gl::PixelUnpackState &unpack, const uint8_t *pixelData);
 
   protected:
-    TextureStorage11(Renderer *renderer, UINT bindFlags);
-    void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest);
+    TextureStorage11(Renderer11 *renderer, UINT bindFlags);
     int getLevelWidth(int mipLevel) const;
     int getLevelHeight(int mipLevel) const;
     int getLevelDepth(int mipLevel) const;
 
-    virtual ID3D11Resource *getSwizzleTexture() = 0;
-    virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel) = 0;
-    ID3D11ShaderResourceView *getSRVLevel(int mipLevel);
+    virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0;
+    virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0;
+    gl::Error getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV);
 
-    virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) = 0;
+    virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+                                ID3D11ShaderResourceView **outSRV) const = 0;
 
     void verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
 
@@ -89,6 +90,7 @@ class TextureStorage11 : public TextureStorage
     int mTopLevel;
     unsigned int mMipLevels;
 
+    GLenum mInternalFormat;
     DXGI_FORMAT mTextureFormat;
     DXGI_FORMAT mShaderResourceFormat;
     DXGI_FORMAT mRenderTargetFormat;
@@ -115,69 +117,53 @@ class TextureStorage11 : public TextureStorage
     };
     SwizzleCacheValue mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
 
+  private:
+    DISALLOW_COPY_AND_ASSIGN(TextureStorage11);
+
+    const UINT mBindFlags;
+
     struct SRVKey
     {
         SRVKey(int baseLevel = 0, int mipLevels = 0, bool swizzle = false);
 
-        bool operator==(const SRVKey &rhs) const;
+        bool operator<(const SRVKey &rhs) const;
 
         int baseLevel;
         int mipLevels;
         bool swizzle;
     };
+    typedef std::map<SRVKey, ID3D11ShaderResourceView *> SRVCache;
 
-    struct SRVPair
-    {
-        SRVKey key;
-        ID3D11ShaderResourceView *srv;
-    };
-
-    struct SRVCache
-    {
-        ~SRVCache();
-
-        ID3D11ShaderResourceView *find(const SRVKey &key) const;
-        ID3D11ShaderResourceView *add(const SRVKey &key, ID3D11ShaderResourceView *srv);
-
-        std::vector<SRVPair> cache;
-    };
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureStorage11);
-
-    const UINT mBindFlags;
-
-    SRVCache srvCache;
+    SRVCache mSrvCache;
     ID3D11ShaderResourceView *mLevelSRVs[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
 };
 
 class TextureStorage11_2D : public TextureStorage11
 {
   public:
-    TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain);
-    TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
+    TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain);
+    TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
     virtual ~TextureStorage11_2D();
 
     static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage);
 
-    virtual ID3D11Resource *getResource() const;
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
-
-    virtual void generateMipmaps();
+    virtual gl::Error getResource(ID3D11Resource **outResource);
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
 
-    virtual void associateImage(Image11* image, int level, int layerTarget);
-    virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage);
-    virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage);
-    virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage);
+    virtual void associateImage(Image11* image, const gl::ImageIndex &index);
+    virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
 
   protected:
-    virtual ID3D11Resource *getSwizzleTexture();
-    virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel);
+    virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
+    virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D);
 
-    virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture);
+    virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+                                ID3D11ShaderResourceView **outSRV) const;
 
     ID3D11Texture2D *mTexture;
     RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
@@ -191,68 +177,68 @@ class TextureStorage11_2D : public TextureStorage11
 class TextureStorage11_Cube : public TextureStorage11
 {
   public:
-    TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels);
+    TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels);
     virtual ~TextureStorage11_Cube();
 
     static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage);
 
-    virtual ID3D11Resource *getResource() const;
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
-
-    virtual void generateMipmaps();
+    virtual gl::Error getResource(ID3D11Resource **outResource);
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
 
-    virtual void associateImage(Image11* image, int level, int layerTarget);
-    virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage);
-    virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage);
-    virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage);
+    virtual void associateImage(Image11* image, const gl::ImageIndex &index);
+    virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
 
   protected:
-    virtual ID3D11Resource *getSwizzleTexture();
-    virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel);
+    virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
+    virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube);
 
-    virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture);
+    virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+                                ID3D11ShaderResourceView **outSRV) const;
+
+    static const size_t CUBE_FACE_COUNT = 6;
 
     ID3D11Texture2D *mTexture;
-    RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+    RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
 
     ID3D11Texture2D *mSwizzleTexture;
     ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
 
-    Image11 *mAssociatedImages[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+    Image11 *mAssociatedImages[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
 };
 
 class TextureStorage11_3D : public TextureStorage11
 {
   public:
-    TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget,
+    TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
                         GLsizei width, GLsizei height, GLsizei depth, int levels);
     virtual ~TextureStorage11_3D();
 
     static TextureStorage11_3D *makeTextureStorage11_3D(TextureStorage *storage);
 
-    virtual ID3D11Resource *getResource() const;
+    virtual gl::Error getResource(ID3D11Resource **outResource);
 
     // Handles both layer and non-layer RTs
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
-
-    virtual void generateMipmaps();
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
 
-    virtual void associateImage(Image11* image, int level, int layerTarget);
-    virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage);
-    virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage);
-    virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage);
+    virtual void associateImage(Image11* image, const gl::ImageIndex &index);
+    virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
 
   protected:
-    virtual ID3D11Resource *getSwizzleTexture();
-    virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel);
+    virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
+    virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureStorage11_3D);
 
-    virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture);
+    virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+                                ID3D11ShaderResourceView **outSRV) const;
 
     typedef std::pair<int, int> LevelLayerKey;
     typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap;
@@ -270,30 +256,29 @@ class TextureStorage11_3D : public TextureStorage11
 class TextureStorage11_2DArray : public TextureStorage11
 {
   public:
-    TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget,
+    TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
                              GLsizei width, GLsizei height, GLsizei depth, int levels);
     virtual ~TextureStorage11_2DArray();
 
     static TextureStorage11_2DArray *makeTextureStorage11_2DArray(TextureStorage *storage);
 
-    virtual ID3D11Resource *getResource() const;
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
-
-    virtual void generateMipmaps();
+    virtual gl::Error getResource(ID3D11Resource **outResource);
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
 
-    virtual void associateImage(Image11* image, int level, int layerTarget);
-    virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage);
-    virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage);
-    virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage);
+    virtual void associateImage(Image11* image, const gl::ImageIndex &index);
+    virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
+    virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
 
   protected:
-    virtual ID3D11Resource *getSwizzleTexture();
-    virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel);
+    virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
+    virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2DArray);
 
-    virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture);
+    virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
+                                ID3D11ShaderResourceView **outSRV) const;
 
     typedef std::pair<int, int> LevelLayerKey;
     typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h
index 590cb9f05a4..70bc3bb26f3 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h
@@ -19,7 +19,7 @@ class Renderer11;
 class VertexArray11 : public VertexArrayImpl
 {
   public:
-    VertexArray11(rx::Renderer11 *renderer)
+    VertexArray11(Renderer11 *renderer)
         : VertexArrayImpl(),
           mRenderer(renderer)
     {
@@ -34,7 +34,7 @@ class VertexArray11 : public VertexArrayImpl
   private:
     DISALLOW_COPY_AND_ASSIGN(VertexArray11);
 
-    rx::Renderer11 *mRenderer;
+    Renderer11 *mRenderer;
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp
index 9bc5b1d2d16..a9d6fa2ca43 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp
@@ -16,7 +16,7 @@
 namespace rx
 {
 
-VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer)
+VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
 {
     mBuffer = NULL;
     mBufferSize = 0;
@@ -91,8 +91,13 @@ gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attri
     {
         if (buffer)
         {
-            Buffer11 *storage = Buffer11::makeBuffer11(buffer->getImplementation());
-            input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset);
+            BufferD3D *storage = BufferD3D::makeFromBuffer(buffer);
+            gl::Error error = storage->getData(&input);
+            if (error.isError())
+            {
+                return error;
+            }
+            input += static_cast<int>(attrib.offset);
         }
         else
         {
@@ -132,7 +137,7 @@ gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GL
         else
         {
             // Round up to divisor, if possible
-            elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
+            elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
         }
 
         gl::VertexFormat vertexFormat(attrib);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h
index 0e10da1df88..a9bbac98fad 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h
@@ -18,7 +18,7 @@ class Renderer11;
 class VertexBuffer11 : public VertexBuffer
 {
   public:
-    explicit VertexBuffer11(rx::Renderer11 *const renderer);
+    explicit VertexBuffer11(Renderer11 *const renderer);
     virtual ~VertexBuffer11();
 
     virtual gl::Error initialize(unsigned int size, bool dynamicUsage);
@@ -40,7 +40,7 @@ class VertexBuffer11 : public VertexBuffer
   private:
     DISALLOW_COPY_AND_ASSIGN(VertexBuffer11);
 
-    rx::Renderer11 *const mRenderer;
+    Renderer11 *const mRenderer;
 
     ID3D11Buffer *mBuffer;
     unsigned int mBufferSize;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
index c07828757d8..90a879e170b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
@@ -795,7 +795,7 @@ static D3D11ES3FormatMap BuildD3D11FormatMap()
 
     // From GL_EXT_texture_storage
     //                           | GL internal format     | D3D11 texture format          | D3D11 SRV format                    | D3D11 RTV format              | D3D11 DSV format               |
-    InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT,             DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_UNKNOWN           );
+    InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT,             DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_UNKNOWN           );
     InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT,         DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_UNKNOWN           );
     InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT,           DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT,       DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN           );
     InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT,       DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT,       DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN           );
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
index 2af97e73f04..121aa3bbadf 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -10,6 +10,7 @@
 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
 #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libGLESv2/renderer/Workarounds.h"
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/Framebuffer.h"
 
@@ -95,9 +96,6 @@
 #ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT
 #  define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32
 #endif
-#ifndef D3D11_VS_OUTPUT_REGISTER_COUNT
-#  define D3D11_VS_OUTPUT_REGISTER_COUNT 32
-#endif
 
 namespace rx
 {
@@ -357,7 +355,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0:
@@ -377,7 +375,7 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY;
@@ -399,7 +397,7 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0:
@@ -421,7 +419,7 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
 
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0:
@@ -441,7 +439,7 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
 
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0:
@@ -466,7 +464,7 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
 
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0:
@@ -486,7 +484,7 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel
 
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
@@ -506,7 +504,7 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
@@ -526,7 +524,7 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION;
@@ -546,7 +544,7 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
@@ -566,7 +564,7 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
@@ -586,7 +584,7 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX;
@@ -612,7 +610,7 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)
 
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0:
@@ -636,7 +634,7 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)
 
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0:
@@ -655,7 +653,7 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT;
@@ -677,7 +675,7 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
     // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
@@ -704,7 +702,7 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers();
@@ -733,7 +731,7 @@ static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
 
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
@@ -754,7 +752,7 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
@@ -778,7 +776,7 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
     // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
@@ -805,7 +803,7 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers();
@@ -826,7 +824,7 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
@@ -847,7 +845,7 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
@@ -868,7 +866,7 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
@@ -889,7 +887,7 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
@@ -914,7 +912,7 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)
 
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
@@ -935,7 +933,7 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT;
@@ -951,11 +949,11 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
     }
 }
 
-static size_t GetMaximumStreamOutputInterleavedComponenets(D3D_FEATURE_LEVEL featureLevel)
+static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
       case D3D_FEATURE_LEVEL_11_0:
@@ -971,14 +969,14 @@ static size_t GetMaximumStreamOutputInterleavedComponenets(D3D_FEATURE_LEVEL fea
     }
 }
 
-static size_t GetMaximumStreamOutputSeparateCompeonents(D3D_FEATURE_LEVEL featureLevel)
+static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel)
 {
     switch (featureLevel)
     {
-#if _MSC_VER >= 1700
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
       case D3D_FEATURE_LEVEL_11_1:
 #endif
-      case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponenets(featureLevel) /
+      case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) /
                                           GetMaximumStreamOutputBuffers(featureLevel);
 
 
@@ -1087,9 +1085,9 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text
     caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
 
     // Transform feedback limits
-    caps->maxTransformFeedbackInterleavedComponents = GetMaximumStreamOutputInterleavedComponenets(featureLevel);
+    caps->maxTransformFeedbackInterleavedComponents = GetMaximumStreamOutputInterleavedComponents(featureLevel);
     caps->maxTransformFeedbackSeparateAttributes = GetMaximumStreamOutputBuffers(featureLevel);
-    caps->maxTransformFeedbackSeparateComponents = GetMaximumStreamOutputSeparateCompeonents(featureLevel);
+    caps->maxTransformFeedbackSeparateComponents = GetMaximumStreamOutputSeparateComponents(featureLevel);
 
     // GL extension support
     extensions->setTextureExtensionSupport(*textureCapsMap);
@@ -1198,17 +1196,31 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo
 
 HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
 {
-#if !defined(__MINGW32__) && defined(_DEBUG)
+#if defined(_DEBUG) && !defined(__MINGW32__)
     return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name);
 #else
     return S_OK;
 #endif
 }
 
-RenderTarget11 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
+gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget11 **outRT)
+{
+    RenderTarget *renderTarget = NULL;
+    gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget);
+    if (error.isError())
+    {
+        return error;
+    }
+    *outRT = RenderTarget11::makeRenderTarget11(renderTarget);
+    return gl::Error(GL_NO_ERROR);
+}
+
+Workarounds GenerateWorkarounds()
 {
-    RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
-    return RenderTarget11::makeRenderTarget11(renderTarget);
+    Workarounds workarounds;
+    workarounds.mrtPerfWorkaround = true;
+    workarounds.setDataFasterThanImageUpload = true;
+    return workarounds;
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h
index 4c05eb92562..9df9c95763e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h
@@ -12,6 +12,7 @@
 
 #include "libGLESv2/angletypes.h"
 #include "libGLESv2/Caps.h"
+#include "libGLESv2/Error.h"
 
 #include <vector>
 
@@ -23,6 +24,7 @@ class FramebufferAttachment;
 namespace rx
 {
 class RenderTarget11;
+struct Workarounds;
 
 namespace gl_d3d11
 {
@@ -176,7 +178,9 @@ inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBu
     context->Unmap(constantBuffer, 0);
 }
 
-RenderTarget11 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment);
+gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget11 **outRT);
+
+Workarounds GenerateWorkarounds();
 
 }
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp
index f061a32c52b..2ca7a9cf8a6 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp
@@ -46,10 +46,16 @@ const size_t g_shaderSize[] =
 
 namespace rx
 {
-Blit9::Blit9(rx::Renderer9 *renderer)
-  : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL)
+
+Blit9::Blit9(Renderer9 *renderer)
+    : mRenderer(renderer),
+      mGeometryLoaded(false),
+      mQuadVertexBuffer(NULL),
+      mQuadVertexDeclaration(NULL),
+      mSavedStateBlock(NULL),
+      mSavedRenderTarget(NULL),
+      mSavedDepthStencil(NULL)
 {
-    initGeometry();
     memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
 }
 
@@ -65,8 +71,13 @@ Blit9::~Blit9()
     }
 }
 
-void Blit9::initGeometry()
+gl::Error Blit9::initialize()
 {
+    if (mGeometryLoaded)
+    {
+        return gl::Error(GL_NO_ERROR);
+    }
+
     static const float quad[] =
     {
         -1, -1,
@@ -82,7 +93,7 @@ void Blit9::initGeometry()
     if (FAILED(result))
     {
         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-        return gl::error(GL_OUT_OF_MEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal blit vertex shader, result: 0x%X.", result);
     }
 
     void *lockPtr = NULL;
@@ -91,7 +102,8 @@ void Blit9::initGeometry()
     if (FAILED(result) || lockPtr == NULL)
     {
         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-        return gl::error(GL_OUT_OF_MEMORY);
+        SafeRelease(mQuadVertexBuffer);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex shader, result: 0x%X.", result);
     }
 
     memcpy(lockPtr, quad, sizeof(quad));
@@ -108,14 +120,18 @@ void Blit9::initGeometry()
     if (FAILED(result))
     {
         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-        return gl::error(GL_OUT_OF_MEMORY);
+        SafeRelease(mQuadVertexBuffer);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex declaration, result: 0x%X.", result);
     }
+
+    mGeometryLoaded = true;
+    return gl::Error(GL_NO_ERROR);
 }
 
 template <class D3DShaderType>
-bool Blit9::setShader(ShaderId source, const char *profile,
-                     D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length),
-                     HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
+gl::Error Blit9::setShader(ShaderId source, const char *profile,
+                           gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader),
+                           HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
 {
     IDirect3DDevice9 *device = mRenderer->getDevice();
 
@@ -130,35 +146,32 @@ bool Blit9::setShader(ShaderId source, const char *profile,
         const BYTE* shaderCode = g_shaderCode[source];
         size_t shaderSize = g_shaderSize[source];
 
-        shader = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize);
-        if (!shader)
+        gl::Error error = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize, &shader);
+        if (error.isError())
         {
-            ERR("Failed to create shader for blit operation");
-            return false;
+            return error;
         }
 
         mCompiledShaders[source] = shader;
     }
 
     HRESULT hr = (device->*setShader)(shader);
-
     if (FAILED(hr))
     {
-        ERR("Failed to set shader for blit operation");
-        return false;
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to set shader for blit operation, result: 0x%X.", hr);
     }
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Blit9::setVertexShader(ShaderId shader)
+gl::Error Blit9::setVertexShader(ShaderId shader)
 {
-    return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader);
+    return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader);
 }
 
-bool Blit9::setPixelShader(ShaderId shader)
+gl::Error Blit9::setPixelShader(ShaderId shader)
 {
-    return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader);
+    return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader);
 }
 
 RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const
@@ -175,12 +188,19 @@ RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const
     return rect;
 }
 
-bool Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
+gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
 {
-    IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
-    if (!texture)
+    gl::Error error = initialize();
+    if (error.isError())
     {
-        return false;
+        return error;
+    }
+
+    IDirect3DTexture9 *texture = NULL;
+    error = copySurfaceToTexture(source, getSurfaceRect(source), &texture);
+    if (error.isError())
+    {
+        return error;
     }
 
     IDirect3DDevice9 *device = mRenderer->getDevice();
@@ -205,87 +225,90 @@ bool Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
 
     restoreState();
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
+gl::Error Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
 {
-    RenderTarget9 *renderTarget = NULL;
-    IDirect3DSurface9 *source = NULL;
-    gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
-
-    if (colorbuffer)
+    gl::Error error = initialize();
+    if (error.isError())
     {
-        renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer);
+        return error;
     }
 
-    if (renderTarget)
-    {
-        source = renderTarget->getSurface();
-    }
+    gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
+    ASSERT(colorbuffer);
 
-    if (!source)
+    RenderTarget9 *renderTarget9 = NULL;
+    error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget9);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(renderTarget9);
 
-    TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage);
-    IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true);
-    bool result = false;
+    IDirect3DSurface9 *source = renderTarget9->getSurface();
+    ASSERT(source);
 
-    if (destSurface)
+    IDirect3DSurface9 *destSurface = NULL;
+    TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage);
+    error = storage9->getSurfaceLevel(level, true, &destSurface);
+    if (error.isError())
     {
-        result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
-        SafeRelease(destSurface);
+        return error;
     }
+    ASSERT(destSurface);
+
+    gl::Error result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
 
+    SafeRelease(destSurface);
     SafeRelease(source);
+
     return result;
 }
 
-bool Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
+gl::Error Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
 {
-    RenderTarget9 *renderTarget = NULL;
-    IDirect3DSurface9 *source = NULL;
-    gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
-
-    if (colorbuffer)
+    gl::Error error = initialize();
+    if (error.isError())
     {
-        renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer);
+        return error;
     }
 
-    if (renderTarget)
-    {
-        source = renderTarget->getSurface();
-    }
+    gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
+    ASSERT(colorbuffer);
 
-    if (!source)
+    RenderTarget9 *renderTarget9 = NULL;
+    error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget9);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(renderTarget9);
 
-    TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage);
-    IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true);
-    bool result = false;
+    IDirect3DSurface9 *source = renderTarget9->getSurface();
+    ASSERT(source);
 
-    if (destSurface)
+    IDirect3DSurface9 *destSurface = NULL;
+    TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage);
+    error = storage9->getCubeMapSurface(target, level, true, &destSurface);
+    if (error.isError())
     {
-        result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
-        SafeRelease(destSurface);
+        return error;
     }
+    ASSERT(destSurface);
+
+    gl::Error result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
 
+    SafeRelease(destSurface);
     SafeRelease(source);
+
     return result;
 }
 
-bool Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
+gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
 {
-    if (!dest)
-    {
-        return false;
-    }
+    ASSERT(source != NULL && dest != NULL);
 
     IDirect3DDevice9 *device = mRenderer->getDevice();
 
@@ -303,22 +326,30 @@ bool Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destF
         if (FAILED(result))
         {
             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            return gl::error(GL_OUT_OF_MEMORY, false);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit between textures, StretchRect result: 0x%X.", result);
         }
+
+        return gl::Error(GL_NO_ERROR);
     }
     else
     {
         return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
     }
-    return true;
 }
 
-bool Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
+gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
 {
-    IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
-    if (!texture)
+    gl::Error error = initialize();
+    if (error.isError())
     {
-        return false;
+        return error;
+    }
+
+    IDirect3DTexture9 *texture = NULL;
+    error = copySurfaceToTexture(source, sourceRect, &texture);
+    if (error.isError())
+    {
+        return error;
     }
 
     IDirect3DDevice9 *device = mRenderer->getDevice();
@@ -331,7 +362,9 @@ bool Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLe
     setViewport(sourceRect, xoffset, yoffset);
 
     setCommonBlitState();
-    if (setFormatConvertShaders(destFormat))
+
+    error = setFormatConvertShaders(destFormat);
+    if (!error.isError())
     {
         render();
     }
@@ -340,12 +373,16 @@ bool Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLe
 
     restoreState();
 
-    return true;
+    return error;
 }
 
-bool Blit9::setFormatConvertShaders(GLenum destFormat)
+gl::Error Blit9::setFormatConvertShaders(GLenum destFormat)
 {
-    bool okay = setVertexShader(SHADER_VS_STANDARD);
+    gl::Error error = setVertexShader(SHADER_VS_STANDARD);
+    if (error.isError())
+    {
+        return error;
+    }
 
     switch (destFormat)
     {
@@ -356,18 +393,18 @@ bool Blit9::setFormatConvertShaders(GLenum destFormat)
       case GL_RG_EXT:
       case GL_RED_EXT:
       case GL_ALPHA:
-        okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
+        error = setPixelShader(SHADER_PS_COMPONENTMASK);
         break;
 
       case GL_LUMINANCE:
       case GL_LUMINANCE_ALPHA:
-        okay = okay && setPixelShader(SHADER_PS_LUMINANCE);
+        error = setPixelShader(SHADER_PS_LUMINANCE);
         break;
     }
 
-    if (!okay)
+    if (error.isError())
     {
-        return false;
+        return error;
     }
 
     enum { X = 0, Y = 1, Z = 2, W = 3 };
@@ -463,15 +500,12 @@ bool Blit9::setFormatConvertShaders(GLenum destFormat)
 
     mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2);
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-IDirect3DTexture9 *Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
+gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture)
 {
-    if (!surface)
-    {
-        return NULL;
-    }
+    ASSERT(surface);
 
     IDirect3DDevice9 *device = mRenderer->getDevice();
 
@@ -485,7 +519,7 @@ IDirect3DTexture9 *Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const
     if (FAILED(result))
     {
         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-        return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for blit, result: 0x%X.", result);
     }
 
     IDirect3DSurface9 *textureSurface;
@@ -495,7 +529,7 @@ IDirect3DTexture9 *Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const
     {
         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
         SafeRelease(texture);
-        return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to query surface of internal blit texture, result: 0x%X.", result);
     }
 
     mRenderer->endScene();
@@ -507,10 +541,11 @@ IDirect3DTexture9 *Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const
     {
         ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
         SafeRelease(texture);
-        return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy between internal blit textures, result: 0x%X.", result);
     }
 
-    return texture;
+    *outTexture = texture;
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Blit9::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h
index 46a3ee1cf36..5c7a76ce055 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h
@@ -10,6 +10,7 @@
 #define LIBGLESV2_BLIT9_H_
 
 #include "common/angleutils.h"
+#include "libGLESv2/Error.h"
 
 #include <GLES2/gl2.h>
 
@@ -29,32 +30,33 @@ class Blit9
     explicit Blit9(Renderer9 *renderer);
     ~Blit9();
 
+    gl::Error initialize();
+
     // Copy from source surface to dest surface.
     // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
-    bool copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level);
-    bool copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level);
+    gl::Error copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level);
+    gl::Error copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level);
 
     // Copy from source surface to dest surface.
     // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
     // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0.
-    bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
+    gl::Error formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
 
     // 2x2 box filter sample from source to dest.
     // Requires that source is RGB(A) and dest has the same format as source.
-    bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
+    gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
 
   private:
-    rx::Renderer9 *mRenderer;
+    Renderer9 *mRenderer;
 
+    bool mGeometryLoaded;
     IDirect3DVertexBuffer9 *mQuadVertexBuffer;
     IDirect3DVertexDeclaration9 *mQuadVertexDeclaration;
 
-    void initGeometry();
-
-    bool setFormatConvertShaders(GLenum destFormat);
+    gl::Error setFormatConvertShaders(GLenum destFormat);
 
-    bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
-    IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect);
+    gl::Error copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
+    gl::Error copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture);
     void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset);
     void setCommonBlitState();
     RECT getSurfaceRect(IDirect3DSurface9 *surface) const;
@@ -74,12 +76,12 @@ class Blit9
     IUnknown *mCompiledShaders[SHADER_COUNT];
 
     template <class D3DShaderType>
-    bool setShader(ShaderId source, const char *profile,
-                   D3DShaderType *(Renderer9::*createShader)(const DWORD *, size_t length),
-                   HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*));
+    gl::Error setShader(ShaderId source, const char *profile,
+                        gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader),
+                        HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*));
 
-    bool setVertexShader(ShaderId shader);
-    bool setPixelShader(ShaderId shader);
+    gl::Error setVertexShader(ShaderId shader);
+    gl::Error setPixelShader(ShaderId shader);
     void render();
 
     void saveState();
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp
index c02db515a28..430fe81e502 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp
@@ -13,7 +13,7 @@
 namespace rx
 {
 
-Buffer9::Buffer9(rx::Renderer9 *renderer)
+Buffer9::Buffer9(Renderer9 *renderer)
     : BufferD3D(),
       mRenderer(renderer),
       mSize(0)
@@ -41,7 +41,7 @@ gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage)
     }
 
     mSize = size;
-    if (data)
+    if (data && size > 0)
     {
         memcpy(mMemory.data(), data, size);
     }
@@ -56,9 +56,10 @@ gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage)
     return gl::Error(GL_NO_ERROR);
 }
 
-void *Buffer9::getData()
+gl::Error Buffer9::getData(const uint8_t **outData)
 {
-    return mMemory.data();
+    *outData = mMemory.data();
+    return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset)
@@ -72,7 +73,7 @@ gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset)
     }
 
     mSize = std::max(mSize, offset + size);
-    if (data)
+    if (data && size > 0)
     {
         memcpy(mMemory.data() + offset, data, size);
     }
@@ -113,7 +114,7 @@ void Buffer9::markTransformFeedbackUsage()
     UNREACHABLE();
 }
 
-Renderer* Buffer9::getRenderer()
+RendererD3D *Buffer9::getRenderer()
 {
     return mRenderer;
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h
index e78182f9050..c80b0097384 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h
@@ -20,7 +20,7 @@ class Renderer9;
 class Buffer9 : public BufferD3D
 {
   public:
-    Buffer9(rx::Renderer9 *renderer);
+    Buffer9(Renderer9 *renderer);
     virtual ~Buffer9();
 
     static Buffer9 *makeBuffer9(BufferImpl *buffer);
@@ -28,11 +28,11 @@ class Buffer9 : public BufferD3D
     // BufferD3D implementation
     virtual size_t getSize() const { return mSize; }
     virtual bool supportsDirectBinding() const { return false; }
-    virtual Renderer* getRenderer();
+    RendererD3D *getRenderer() override;
 
     // BufferImpl implementation
     virtual gl::Error setData(const void* data, size_t size, GLenum usage);
-    virtual void *getData();
+    gl::Error getData(const uint8_t **outData) override;
     virtual gl::Error setSubData(const void* data, size_t size, size_t offset);
     virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
     virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr);
@@ -42,7 +42,7 @@ class Buffer9 : public BufferD3D
   private:
     DISALLOW_COPY_AND_ASSIGN(Buffer9);
 
-    rx::Renderer9 *mRenderer;
+    Renderer9 *mRenderer;
     MemoryBuffer mMemory;
     size_t mSize;
 };
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp
index e352a5f50af..66263fe110d 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp
@@ -4,7 +4,7 @@
 // found in the LICENSE file.
 //
 
-// Fence9.cpp: Defines the rx::Fence9 class.
+// Fence9.cpp: Defines the rx::FenceNV9 class.
 
 #include "libGLESv2/renderer/d3d/d3d9/Fence9.h"
 #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
@@ -14,39 +14,41 @@
 namespace rx
 {
 
-Fence9::Fence9(rx::Renderer9 *renderer)
+FenceNV9::FenceNV9(Renderer9 *renderer)
+    : FenceNVImpl(),
+      mRenderer(renderer),
+      mQuery(NULL)
 {
-    mRenderer = renderer;
-    mQuery = NULL;
 }
 
-Fence9::~Fence9()
+FenceNV9::~FenceNV9()
 {
     SafeRelease(mQuery);
 }
 
-bool Fence9::isSet() const
-{
-    return mQuery != NULL;
-}
-
-void Fence9::set()
+gl::Error FenceNV9::set()
 {
     if (!mQuery)
     {
-        mQuery = mRenderer->allocateEventQuery();
-        if (!mQuery)
+        gl::Error error = mRenderer->allocateEventQuery(&mQuery);
+        if (error.isError())
         {
-            return gl::error(GL_OUT_OF_MEMORY);
+            return error;
         }
     }
 
     HRESULT result = mQuery->Issue(D3DISSUE_END);
-    UNUSED_ASSERTION_VARIABLE(result);
-    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        SafeRelease(mQuery);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to end event query, result: 0x%X.", result);
+    }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Fence9::test(bool flushCommandBuffer)
+gl::Error FenceNV9::test(bool flushCommandBuffer, GLboolean *outFinished)
 {
     ASSERT(mQuery);
 
@@ -56,17 +58,34 @@ bool Fence9::test(bool flushCommandBuffer)
     if (d3d9::isDeviceLostError(result))
     {
         mRenderer->notifyDeviceLost();
-        return gl::error(GL_OUT_OF_MEMORY, true);
+        return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query.");
+    }
+    else if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result);
     }
 
     ASSERT(result == S_OK || result == S_FALSE);
-
-    return (result == S_OK);
+    *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Fence9::hasError() const
+gl::Error FenceNV9::finishFence(GLboolean *outFinished)
 {
-    return mRenderer->isDeviceLost();
+    ASSERT(outFinished);
+
+    while (*outFinished != GL_TRUE)
+    {
+        gl::Error error = test(true, outFinished);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        Sleep(0);
+    }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h
index e923a2178cf..d7873d52648 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h
@@ -4,7 +4,7 @@
 // found in the LICENSE file.
 //
 
-// Fence9.h: Defines the rx::Fence9 class which implements rx::FenceImpl.
+// Fence9.h: Defines the rx::FenceNV9 class which implements rx::FenceNVImpl.
 
 #ifndef LIBGLESV2_RENDERER_FENCE9_H_
 #define LIBGLESV2_RENDERER_FENCE9_H_
@@ -15,21 +15,20 @@ namespace rx
 {
 class Renderer9;
 
-class Fence9 : public FenceImpl
+class FenceNV9 : public FenceNVImpl
 {
   public:
-    explicit Fence9(rx::Renderer9 *renderer);
-    virtual ~Fence9();
+    explicit FenceNV9(Renderer9 *renderer);
+    virtual ~FenceNV9();
 
-    bool isSet() const;
-    void set();
-    bool test(bool flushCommandBuffer);
-    bool hasError() const;
+    gl::Error set();
+    gl::Error test(bool flushCommandBuffer, GLboolean *outFinished);
+    gl::Error finishFence(GLboolean *outFinished);
 
   private:
-    DISALLOW_COPY_AND_ASSIGN(Fence9);
+    DISALLOW_COPY_AND_ASSIGN(FenceNV9);
 
-    rx::Renderer9 *mRenderer;
+    Renderer9 *mRenderer;
     IDirect3DQuery9 *mQuery;
 };
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
index 18383fba78f..2a06d12942a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
@@ -17,7 +17,7 @@
 #include "libGLESv2/Framebuffer.h"
 #include "libGLESv2/FramebufferAttachment.h"
 #include "libGLESv2/Renderbuffer.h"
-
+#include "common/utilities.h"
 
 namespace rx
 {
@@ -36,15 +36,23 @@ Image9::~Image9()
     SafeRelease(mSurface);
 }
 
-void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface)
+gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface)
 {
     D3DSURFACE_DESC destDesc;
     HRESULT result = destSurface->GetDesc(&destDesc);
     ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the source surface description for mipmap generation, result: 0x%X.", result);
+    }
 
     D3DSURFACE_DESC sourceDesc;
     result = sourceSurface->GetDesc(&sourceDesc);
     ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the destination surface description for mipmap generation, result: 0x%X.", result);
+    }
 
     ASSERT(sourceDesc.Format == destDesc.Format);
     ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width);
@@ -56,74 +64,111 @@ void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sour
     D3DLOCKED_RECT sourceLocked = {0};
     result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY);
     ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface for mipmap generation, result: 0x%X.", result);
+    }
 
     D3DLOCKED_RECT destLocked = {0};
     result = destSurface->LockRect(&destLocked, NULL, 0);
     ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
+    {
+        sourceSurface->UnlockRect();
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the destination surface for mipmap generation, result: 0x%X.", result);
+    }
 
     const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(sourceLocked.pBits);
     uint8_t *destData = reinterpret_cast<uint8_t*>(destLocked.pBits);
 
-    if (sourceData && destData)
-    {
-        d3dFormatInfo.mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0,
-                                            destData, destLocked.Pitch, 0);
-    }
+    ASSERT(sourceData && destData);
+
+    d3dFormatInfo.mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0,
+                                        destData, destLocked.Pitch, 0);
 
     destSurface->UnlockRect();
     sourceSurface->UnlockRect();
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 Image9 *Image9::makeImage9(Image *img)
 {
-    ASSERT(HAS_DYNAMIC_TYPE(rx::Image9*, img));
-    return static_cast<rx::Image9*>(img);
+    ASSERT(HAS_DYNAMIC_TYPE(Image9*, img));
+    return static_cast<Image9*>(img);
 }
 
-void Image9::generateMipmap(Image9 *dest, Image9 *source)
+gl::Error Image9::generateMipmap(Image9 *dest, Image9 *source)
 {
-    IDirect3DSurface9 *sourceSurface = source->getSurface();
-    if (sourceSurface == NULL)
-        return gl::error(GL_OUT_OF_MEMORY);
+    IDirect3DSurface9 *sourceSurface = NULL;
+    gl::Error error = source->getSurface(&sourceSurface);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    IDirect3DSurface9 *destSurface = dest->getSurface();
-    generateMip(destSurface, sourceSurface);
+    IDirect3DSurface9 *destSurface = NULL;
+    error = dest->getSurface(&destSurface);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = generateMip(destSurface, sourceSurface);
+    if (error.isError())
+    {
+        return error;
+    }
 
     dest->markDirty();
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source)
+gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source)
 {
     D3DLOCKED_RECT sourceLock = {0};
     D3DLOCKED_RECT destLock = {0};
 
-    source->LockRect(&sourceLock, NULL, 0);
-    dest->LockRect(&destLock, NULL, 0);
+    HRESULT result;
+
+    result = source->LockRect(&sourceLock, NULL, 0);
+    if (FAILED(result))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result);
+    }
 
-    if (sourceLock.pBits && destLock.pBits)
+    result = dest->LockRect(&destLock, NULL, 0);
+    if (FAILED(result))
     {
-        D3DSURFACE_DESC desc;
-        source->GetDesc(&desc);
+        source->UnlockRect();
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result);
+    }
 
-        const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
-        unsigned int rows = desc.Height / d3dFormatInfo.blockHeight;
+    ASSERT(sourceLock.pBits && destLock.pBits);
 
-        unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight);
-        ASSERT(bytes <= static_cast<unsigned int>(sourceLock.Pitch) &&
-               bytes <= static_cast<unsigned int>(destLock.Pitch));
+    D3DSURFACE_DESC desc;
+    source->GetDesc(&desc);
 
-        for(unsigned int i = 0; i < rows; i++)
-        {
-            memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes);
-        }
+    const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+    unsigned int rows = desc.Height / d3dFormatInfo.blockHeight;
 
-        source->UnlockRect();
-        dest->UnlockRect();
+    unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight);
+    ASSERT(bytes <= static_cast<unsigned int>(sourceLock.Pitch) &&
+           bytes <= static_cast<unsigned int>(destLock.Pitch));
+
+    for(unsigned int i = 0; i < rows; i++)
+    {
+        memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes);
     }
-    else UNREACHABLE();
+
+    source->UnlockRect();
+    dest->UnlockRect();
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Image9::redefine(rx::Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease)
+bool Image9::redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease)
 {
     // 3D textures are not supported by the D3D9 backend.
     ASSERT(depth <= 1);
@@ -160,11 +205,11 @@ bool Image9::redefine(rx::Renderer *renderer, GLenum target, GLenum internalform
     return false;
 }
 
-void Image9::createSurface()
+gl::Error Image9::createSurface()
 {
-    if(mSurface)
+    if (mSurface)
     {
-        return;
+        return gl::Error(GL_NO_ERROR);
     }
 
     IDirect3DTexture9 *newTexture = NULL;
@@ -187,8 +232,7 @@ void Image9::createSurface()
         if (FAILED(result))
         {
             ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            ERR("Creating image surface failed.");
-            return gl::error(GL_OUT_OF_MEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create image surface, result: 0x%X.", result);
         }
 
         newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
@@ -206,35 +250,51 @@ void Image9::createSurface()
             D3DLOCKED_RECT lockedRect;
             result = newSurface->LockRect(&lockedRect, &entireRect, 0);
             ASSERT(SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result);
+            }
 
             d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast<uint8_t*>(lockedRect.pBits),
                                                   lockedRect.Pitch, 0);
 
             result = newSurface->UnlockRect();
             ASSERT(SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock image surface, result: 0x%X.", result);
+            }
         }
     }
 
     mSurface = newSurface;
     mDirty = false;
     mD3DPool = poolToUse;
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-HRESULT Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
+gl::Error Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT &rect)
 {
-    createSurface();
-
-    HRESULT result = D3DERR_INVALIDCALL;
+    gl::Error error = createSurface();
+    if (error.isError())
+    {
+        return error;
+    }
 
     if (mSurface)
     {
-        result = mSurface->LockRect(lockedRect, rect, 0);
+        HRESULT result = mSurface->LockRect(lockedRect, &rect, 0);
         ASSERT(SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result);
+        }
 
         mDirty = true;
     }
 
-    return result;
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Image9::unlock()
@@ -263,26 +323,43 @@ bool Image9::isDirty() const
     return (mSurface || d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) && mDirty;
 }
 
-IDirect3DSurface9 *Image9::getSurface()
+gl::Error Image9::getSurface(IDirect3DSurface9 **outSurface)
 {
-    createSurface();
+    gl::Error error = createSurface();
+    if (error.isError())
+    {
+        return error;
+    }
 
-    return mSurface;
+    *outSurface = mSurface;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Image9::setManagedSurface2D(TextureStorage *storage, int level)
+gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level)
 {
+    IDirect3DSurface9 *surface = NULL;
     TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage);
-    setManagedSurface(storage9->getSurfaceLevel(level, false));
+    gl::Error error = storage9->getSurfaceLevel(level, false, &surface);
+    if (error.isError())
+    {
+        return error;
+    }
+    return setManagedSurface(surface);
 }
 
-void Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level)
+gl::Error Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level)
 {
+    IDirect3DSurface9 *surface = NULL;
     TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage);
-    setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false));
+    gl::Error error = storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false, &surface);
+    if (error.isError())
+    {
+        return error;
+    }
+    return setManagedSurface(surface);
 }
 
-void Image9::setManagedSurface(IDirect3DSurface9 *surface)
+gl::Error Image9::setManagedSurface(IDirect3DSurface9 *surface)
 {
     D3DSURFACE_DESC desc;
     surface->GetDesc(&desc);
@@ -292,97 +369,119 @@ void Image9::setManagedSurface(IDirect3DSurface9 *surface)
     {
         if (mSurface)
         {
-            copyLockableSurfaces(surface, mSurface);
+            gl::Error error = copyLockableSurfaces(surface, mSurface);
             SafeRelease(mSurface);
+            if (error.isError())
+            {
+                return error;
+            }
         }
 
         mSurface = surface;
         mD3DPool = desc.Pool;
     }
-}
 
-bool Image9::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
-{
-    ASSERT(getSurface() != NULL);
-    TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage);
-    return copyToSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height);
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Image9::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
 {
-    ASSERT(getSurface() != NULL);
-    TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage);
-    return copyToSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height);
-}
+    gl::Error error = createSurface();
+    if (error.isError())
+    {
+        return error;
+    }
 
-bool Image9::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth)
-{
-    // 3D textures are not supported by the D3D9 backend.
-    UNREACHABLE();
-    return false;
-}
+    IDirect3DSurface9 *destSurface = NULL;
 
-bool Image9::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height)
-{
-    // 2D array textures are not supported by the D3D9 backend.
-    UNREACHABLE();
-    return false;
+    if (index.type == GL_TEXTURE_2D)
+    {
+        TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage);
+        gl::Error error = storage9->getSurfaceLevel(index.mipIndex, true, &destSurface);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+    else
+    {
+        ASSERT(gl::IsCubemapTextureTarget(index.type));
+        TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage);
+        gl::Error error = storage9->getCubeMapSurface(index.type, index.mipIndex, true, &destSurface);
+        if (error.isError())
+        {
+            return error;
+        }
+    }
+
+    error = copyToSurface(destSurface, region.x, region.y, region.width, region.height);
+    SafeRelease(destSurface);
+    return error;
 }
 
-bool Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
 {
     ASSERT(width > 0 && height > 0);
+    ASSERT(destSurface);
 
-    if (!destSurface)
-        return false;
+    IDirect3DSurface9 *sourceSurface = NULL;
+    gl::Error error = getSurface(&sourceSurface);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    IDirect3DSurface9 *sourceSurface = getSurface();
+    ASSERT(sourceSurface && sourceSurface != destSurface);
 
-    if (sourceSurface && sourceSurface != destSurface)
-    {
-        RECT rect;
-        rect.left = xoffset;
-        rect.top = yoffset;
-        rect.right = xoffset + width;
-        rect.bottom = yoffset + height;
+    RECT rect;
+    rect.left = xoffset;
+    rect.top = yoffset;
+    rect.right = xoffset + width;
+    rect.bottom = yoffset + height;
 
-        POINT point = {rect.left, rect.top};
+    POINT point = {rect.left, rect.top};
 
-        IDirect3DDevice9 *device = mRenderer->getDevice();
+    IDirect3DDevice9 *device = mRenderer->getDevice();
 
-        if (mD3DPool == D3DPOOL_MANAGED)
-        {
-            D3DSURFACE_DESC desc;
-            sourceSurface->GetDesc(&desc);
+    if (mD3DPool == D3DPOOL_MANAGED)
+    {
+        D3DSURFACE_DESC desc;
+        sourceSurface->GetDesc(&desc);
 
-            IDirect3DSurface9 *surf = 0;
-            HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
+        IDirect3DSurface9 *surf = 0;
+        HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Internal CreateOffscreenPlainSurface call failed, result: 0x%X.", result);
+        }
 
-            if (SUCCEEDED(result))
-            {
-                copyLockableSurfaces(surf, sourceSurface);
-                result = device->UpdateSurface(surf, &rect, destSurface, &point);
-                ASSERT(SUCCEEDED(result));
-                SafeRelease(surf);
-            }
+        copyLockableSurfaces(surf, sourceSurface);
+        result = device->UpdateSurface(surf, &rect, destSurface, &point);
+        SafeRelease(surf);
+        ASSERT(SUCCEEDED(result));
+        if (FAILED(result))
+        {
+            return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result);
         }
-        else
+    }
+    else
+    {
+        // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
+        HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point);
+        ASSERT(SUCCEEDED(result));
+        if (FAILED(result))
         {
-            // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
-            HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point);
-            UNUSED_ASSERTION_VARIABLE(result);
-            ASSERT(SUCCEEDED(result));
+            return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result);
         }
     }
 
-    SafeRelease(destSurface);
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
 // into the target pixel rectangle.
-void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                      GLint unpackAlignment, GLenum type, const void *input)
+gl::Error Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                           GLint unpackAlignment, GLenum type, const void *input)
 {
     // 3D textures are not supported by the D3D9 backend.
     ASSERT(zoffset == 0 && depth == 1);
@@ -400,10 +499,10 @@ void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width
     };
 
     D3DLOCKED_RECT locked;
-    HRESULT result = lock(&locked, &lockRect);
-    if (FAILED(result))
+    gl::Error error = lock(&locked, lockRect);
+    if (error.isError())
     {
-        return;
+        return error;
     }
 
     d3dFormatInfo.loadFunction(width, height, depth,
@@ -411,10 +510,12 @@ void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width
                                reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0);
 
     unlock();
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                                const void *input)
+gl::Error Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                                     const void *input)
 {
     // 3D textures are not supported by the D3D9 backend.
     ASSERT(zoffset == 0 && depth == 1);
@@ -437,10 +538,10 @@ void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLs
     };
 
     D3DLOCKED_RECT locked;
-    HRESULT result = lock(&locked, &lockRect);
-    if (FAILED(result))
+    gl::Error error = lock(&locked, lockRect);
+    if (error.isError())
     {
-        return;
+        return error;
     }
 
     d3d9FormatInfo.loadFunction(width, height, depth,
@@ -448,33 +549,22 @@ void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLs
                                 reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0);
 
     unlock();
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 // This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
-void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source)
 {
+    ASSERT(source);
+
     // ES3.0 only behaviour to copy into a 3d texture
     ASSERT(zoffset == 0);
 
-    RenderTarget9 *renderTarget = NULL;
-    IDirect3DSurface9 *surface = NULL;
-    gl::FramebufferAttachment *colorbuffer = source->getColorbuffer(0);
-
-    if (colorbuffer)
-    {
-        renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer);
-    }
-
-    if (renderTarget)
-    {
-        surface = renderTarget->getSurface();
-    }
+    RenderTarget9 *renderTarget = RenderTarget9::makeRenderTarget9(source);
 
-    if (!surface)
-    {
-        ERR("Failed to retrieve the render target.");
-        return gl::error(GL_OUT_OF_MEMORY);
-    }
+    IDirect3DSurface9 *surface = renderTarget->getSurface();
+    ASSERT(surface);
 
     IDirect3DDevice9 *device = mRenderer->getDevice();
 
@@ -486,212 +576,200 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y,
 
     if (FAILED(result))
     {
-        ERR("Could not create matching destination surface.");
         SafeRelease(surface);
-        return gl::error(GL_OUT_OF_MEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Could not create matching destination surface, result: 0x%X.", result);
     }
 
     result = device->GetRenderTargetData(surface, renderTargetData);
 
     if (FAILED(result))
     {
-        ERR("GetRenderTargetData unexpectedly failed.");
         SafeRelease(renderTargetData);
         SafeRelease(surface);
-        return gl::error(GL_OUT_OF_MEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "GetRenderTargetData unexpectedly failed, result: 0x%X.", result);
     }
 
-    RECT sourceRect = {x, y, x + width, y + height};
-    RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
+    int width = sourceArea.width;
+    int height = sourceArea.height;
+
+    RECT sourceRect = { sourceArea.x, sourceArea.y, sourceArea.x + width, sourceArea.y + height };
+    RECT destRect = { xoffset, yoffset, xoffset + width, yoffset + height };
 
     D3DLOCKED_RECT sourceLock = {0};
     result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
 
     if (FAILED(result))
     {
-        ERR("Failed to lock the source surface (rectangle might be invalid).");
         SafeRelease(renderTargetData);
         SafeRelease(surface);
-        return gl::error(GL_OUT_OF_MEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface (rectangle might be invalid), result: 0x%X.", result);
     }
 
     D3DLOCKED_RECT destLock = {0};
-    result = lock(&destLock, &destRect);
-
-    if (FAILED(result))
+    gl::Error error = lock(&destLock, destRect);
+    if (error.isError())
     {
-        ERR("Failed to lock the destination surface (rectangle might be invalid).");
         renderTargetData->UnlockRect();
         SafeRelease(renderTargetData);
         SafeRelease(surface);
-        return gl::error(GL_OUT_OF_MEMORY);
+        return error;
     }
 
-    if (destLock.pBits && sourceLock.pBits)
-    {
-        unsigned char *source = (unsigned char*)sourceLock.pBits;
-        unsigned char *dest = (unsigned char*)destLock.pBits;
+    ASSERT(destLock.pBits && sourceLock.pBits);
 
-        switch (description.Format)
+    unsigned char *sourcePixels = (unsigned char*)sourceLock.pBits;
+    unsigned char *destPixels = (unsigned char*)destLock.pBits;
+
+    switch (description.Format)
+    {
+      case D3DFMT_X8R8G8B8:
+      case D3DFMT_A8R8G8B8:
+        switch (getD3DFormat())
         {
           case D3DFMT_X8R8G8B8:
           case D3DFMT_A8R8G8B8:
-            switch(getD3DFormat())
+            for (int y = 0; y < height; y++)
             {
-              case D3DFMT_X8R8G8B8:
-              case D3DFMT_A8R8G8B8:
-                for(int y = 0; y < height; y++)
+                memcpy(destPixels, sourcePixels, 4 * width);
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          case D3DFMT_L8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
                 {
-                    memcpy(dest, source, 4 * width);
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
+                    destPixels[x] = sourcePixels[x * 4 + 2];
                 }
-                break;
-              case D3DFMT_L8:
-                for(int y = 0; y < height; y++)
-                {
-                    for(int x = 0; x < width; x++)
-                    {
-                        dest[x] = source[x * 4 + 2];
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
-                }
-                break;
-              case D3DFMT_A8L8:
-                for(int y = 0; y < height; y++)
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          case D3DFMT_A8L8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
                 {
-                    for(int x = 0; x < width; x++)
-                    {
-                        dest[x * 2 + 0] = source[x * 4 + 2];
-                        dest[x * 2 + 1] = source[x * 4 + 3];
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
+                    destPixels[x * 2 + 0] = sourcePixels[x * 4 + 2];
+                    destPixels[x * 2 + 1] = sourcePixels[x * 4 + 3];
                 }
-                break;
-              default:
-                UNREACHABLE();
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
             }
             break;
-          case D3DFMT_R5G6B5:
-            switch(getD3DFormat())
+          default:
+            UNREACHABLE();
+        }
+        break;
+      case D3DFMT_R5G6B5:
+        switch (getD3DFormat())
+        {
+          case D3DFMT_X8R8G8B8:
+            for (int y = 0; y < height; y++)
             {
-              case D3DFMT_X8R8G8B8:
-                for(int y = 0; y < height; y++)
+                for (int x = 0; x < width; x++)
                 {
-                    for(int x = 0; x < width; x++)
-                    {
-                        unsigned short rgb = ((unsigned short*)source)[x];
-                        unsigned char red = (rgb & 0xF800) >> 8;
-                        unsigned char green = (rgb & 0x07E0) >> 3;
-                        unsigned char blue = (rgb & 0x001F) << 3;
-                        dest[x + 0] = blue | (blue >> 5);
-                        dest[x + 1] = green | (green >> 6);
-                        dest[x + 2] = red | (red >> 5);
-                        dest[x + 3] = 0xFF;
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
+                    unsigned short rgb = ((unsigned short*)sourcePixels)[x];
+                    unsigned char red = (rgb & 0xF800) >> 8;
+                    unsigned char green = (rgb & 0x07E0) >> 3;
+                    unsigned char blue = (rgb & 0x001F) << 3;
+                    destPixels[x + 0] = blue | (blue >> 5);
+                    destPixels[x + 1] = green | (green >> 6);
+                    destPixels[x + 2] = red | (red >> 5);
+                    destPixels[x + 3] = 0xFF;
                 }
-                break;
-              case D3DFMT_L8:
-                for(int y = 0; y < height; y++)
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          case D3DFMT_L8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
                 {
-                    for(int x = 0; x < width; x++)
-                    {
-                        unsigned char red = source[x * 2 + 1] & 0xF8;
-                        dest[x] = red | (red >> 5);
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
+                    unsigned char red = sourcePixels[x * 2 + 1] & 0xF8;
+                    destPixels[x] = red | (red >> 5);
                 }
-                break;
-              default:
-                UNREACHABLE();
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
             }
             break;
-          case D3DFMT_A1R5G5B5:
-            switch(getD3DFormat())
+          default:
+            UNREACHABLE();
+        }
+        break;
+      case D3DFMT_A1R5G5B5:
+        switch (getD3DFormat())
+        {
+          case D3DFMT_X8R8G8B8:
+            for (int y = 0; y < height; y++)
             {
-              case D3DFMT_X8R8G8B8:
-                for(int y = 0; y < height; y++)
+                for (int x = 0; x < width; x++)
                 {
-                    for(int x = 0; x < width; x++)
-                    {
-                        unsigned short argb = ((unsigned short*)source)[x];
-                        unsigned char red = (argb & 0x7C00) >> 7;
-                        unsigned char green = (argb & 0x03E0) >> 2;
-                        unsigned char blue = (argb & 0x001F) << 3;
-                        dest[x + 0] = blue | (blue >> 5);
-                        dest[x + 1] = green | (green >> 5);
-                        dest[x + 2] = red | (red >> 5);
-                        dest[x + 3] = 0xFF;
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
+                    unsigned short argb = ((unsigned short*)sourcePixels)[x];
+                    unsigned char red = (argb & 0x7C00) >> 7;
+                    unsigned char green = (argb & 0x03E0) >> 2;
+                    unsigned char blue = (argb & 0x001F) << 3;
+                    destPixels[x + 0] = blue | (blue >> 5);
+                    destPixels[x + 1] = green | (green >> 5);
+                    destPixels[x + 2] = red | (red >> 5);
+                    destPixels[x + 3] = 0xFF;
                 }
-                break;
-              case D3DFMT_A8R8G8B8:
-                for(int y = 0; y < height; y++)
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          case D3DFMT_A8R8G8B8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
                 {
-                    for(int x = 0; x < width; x++)
-                    {
-                        unsigned short argb = ((unsigned short*)source)[x];
-                        unsigned char red = (argb & 0x7C00) >> 7;
-                        unsigned char green = (argb & 0x03E0) >> 2;
-                        unsigned char blue = (argb & 0x001F) << 3;
-                        unsigned char alpha = (signed short)argb >> 15;
-                        dest[x + 0] = blue | (blue >> 5);
-                        dest[x + 1] = green | (green >> 5);
-                        dest[x + 2] = red | (red >> 5);
-                        dest[x + 3] = alpha;
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
+                    unsigned short argb = ((unsigned short*)sourcePixels)[x];
+                    unsigned char red = (argb & 0x7C00) >> 7;
+                    unsigned char green = (argb & 0x03E0) >> 2;
+                    unsigned char blue = (argb & 0x001F) << 3;
+                    unsigned char alpha = (signed short)argb >> 15;
+                    destPixels[x + 0] = blue | (blue >> 5);
+                    destPixels[x + 1] = green | (green >> 5);
+                    destPixels[x + 2] = red | (red >> 5);
+                    destPixels[x + 3] = alpha;
                 }
-                break;
-              case D3DFMT_L8:
-                for(int y = 0; y < height; y++)
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          case D3DFMT_L8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
                 {
-                    for(int x = 0; x < width; x++)
-                    {
-                        unsigned char red = source[x * 2 + 1] & 0x7C;
-                        dest[x] = (red << 1) | (red >> 4);
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
+                    unsigned char red = sourcePixels[x * 2 + 1] & 0x7C;
+                    destPixels[x] = (red << 1) | (red >> 4);
                 }
-                break;
-              case D3DFMT_A8L8:
-                for(int y = 0; y < height; y++)
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
+            }
+            break;
+          case D3DFMT_A8L8:
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
                 {
-                    for(int x = 0; x < width; x++)
-                    {
-                        unsigned char red = source[x * 2 + 1] & 0x7C;
-                        dest[x * 2 + 0] = (red << 1) | (red >> 4);
-                        dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
-                    }
-
-                    source += sourceLock.Pitch;
-                    dest += destLock.Pitch;
+                    unsigned char red = sourcePixels[x * 2 + 1] & 0x7C;
+                    destPixels[x * 2 + 0] = (red << 1) | (red >> 4);
+                    destPixels[x * 2 + 1] = (signed char)sourcePixels[x * 2 + 1] >> 7;
                 }
-                break;
-              default:
-                UNREACHABLE();
+                sourcePixels += sourceLock.Pitch;
+                destPixels += destLock.Pitch;
             }
             break;
           default:
             UNREACHABLE();
         }
+        break;
+      default:
+        UNREACHABLE();
     }
 
     unlock();
@@ -701,6 +779,14 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y,
     SafeRelease(surface);
 
     mDirty = true;
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &area, const gl::ImageIndex &srcIndex, TextureStorage *srcStorage)
+{
+    // Currently unreachable, due to only being used in a D3D11-only workaround
+    UNIMPLEMENTED();
+    return gl::Error(GL_INVALID_OPERATION);
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h
index 08d8ee35450..8cc22588599 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h
@@ -20,7 +20,6 @@ class Framebuffer;
 
 namespace rx
 {
-class Renderer;
 class Renderer9;
 
 class Image9 : public ImageD3D
@@ -31,41 +30,41 @@ class Image9 : public ImageD3D
 
     static Image9 *makeImage9(Image *img);
 
-    static void generateMipmap(Image9 *dest, Image9 *source);
-    static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface);
-    static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source);
+    static gl::Error generateMipmap(Image9 *dest, Image9 *source);
+    static gl::Error generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface);
+    static gl::Error copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source);
 
-    virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease);
+    bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) override;
 
     D3DFORMAT getD3DFormat() const;
 
     virtual bool isDirty() const;
-    IDirect3DSurface9 *getSurface();
 
-    virtual void setManagedSurface2D(TextureStorage *storage, int level);
-    virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level);
-    virtual bool copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-    virtual bool copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
-    virtual bool copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
-    virtual bool copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height);
+    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);
 
-    virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                          GLint unpackAlignment, GLenum type, const void *input);
-    virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
-                                    const void *input);
+    virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                               GLint unpackAlignment, GLenum type, const void *input);
+    virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
+                                         const void *input);
 
-    virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset,GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+    virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source);
+    virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea,
+                           const gl::ImageIndex &sourceIndex, TextureStorage *source);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Image9);
 
-    void createSurface();
-    void setManagedSurface(IDirect3DSurface9 *surface);
-    bool copyToSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+    gl::Error getSurface(IDirect3DSurface9 **outSurface);
 
-    HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect);
+    gl::Error createSurface();
+    gl::Error setManagedSurface(IDirect3DSurface9 *surface);
+    gl::Error copyToSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+    gl::Error lock(D3DLOCKED_RECT *lockedRect, const RECT &rect);
     void unlock();
-    
+
     Renderer9 *mRenderer;
 
     D3DPOOL mD3DPool;   // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable.
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h
index d0970d6ac57..2375fcf4b0d 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h
@@ -40,7 +40,7 @@ class IndexBuffer9 : public IndexBuffer
   private:
     DISALLOW_COPY_AND_ASSIGN(IndexBuffer9);
 
-    rx::Renderer9 *const mRenderer;
+    Renderer9 *const mRenderer;
 
     IDirect3DIndexBuffer9 *mIndexBuffer;
     unsigned int mBufferSize;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp
index 815fc01a9b7..a3cab578be1 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp
@@ -15,7 +15,7 @@
 
 namespace rx
 {
-Query9::Query9(rx::Renderer9 *renderer, GLenum type)
+Query9::Query9(Renderer9 *renderer, GLenum type)
     : QueryImpl(type),
       mResult(GL_FALSE),
       mQueryFinished(false),
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h
index 513e0ba6fd5..36851c6c6ca 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h
@@ -18,7 +18,7 @@ class Renderer9;
 class Query9 : public QueryImpl
 {
   public:
-    Query9(rx::Renderer9 *renderer, GLenum type);
+    Query9(Renderer9 *renderer, GLenum type);
     virtual ~Query9();
 
     virtual gl::Error begin();
@@ -34,7 +34,7 @@ class Query9 : public QueryImpl
     GLuint mResult;
     bool mQueryFinished;
 
-    rx::Renderer9 *mRenderer;
+    Renderer9 *mRenderer;
     IDirect3DQuery9 *mQuery;
 };
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp
index 13321ac8cd2..53d1f752fa6 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp
@@ -10,115 +10,83 @@
 #include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
 #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
 #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h"
 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
 #include "libGLESv2/main.h"
 
 namespace rx
 {
 
+RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target)
+{
+    ASSERT(HAS_DYNAMIC_TYPE(RenderTarget9*, target));
+    return static_cast<RenderTarget9*>(target);
+}
+
+void RenderTarget9::invalidate(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+        // Currently a no-op
+}
+
 // TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given.
-RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface)
+TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
+                                           GLsizei samples)
+    : mWidth(width),
+      mHeight(height),
+      mDepth(depth),
+      mInternalFormat(internalFormat),
+      mActualFormat(internalFormat),
+      mSamples(samples),
+      mRenderTarget(surface)
 {
-    mRenderer = Renderer9::makeRenderer9(renderer);
-    mRenderTarget = surface;
+    ASSERT(mDepth == 1);
 
     if (mRenderTarget)
     {
         D3DSURFACE_DESC description;
         mRenderTarget->GetDesc(&description);
 
-        mWidth = description.Width;
-        mHeight = description.Height;
-        mDepth = 1;
-
         const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(description.Format);
-        mInternalFormat = d3dFormatInfo.internalFormat;
         mActualFormat = d3dFormatInfo.internalFormat;
-        mSamples = d3d9_gl::GetSamplesCount(description.MultiSampleType);
     }
 }
 
-RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples)
+TextureRenderTarget9::~TextureRenderTarget9()
 {
-    mRenderer = Renderer9::makeRenderer9(renderer);
-    mRenderTarget = NULL;
-
-    const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalFormat);
-    const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(d3d9FormatInfo.renderFormat);
-
-    const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat);
-    GLuint supportedSamples = textureCaps.getNearestSamples(samples);
+    SafeRelease(mRenderTarget);
+}
 
-    HRESULT result = D3DERR_INVALIDCALL;
+GLsizei TextureRenderTarget9::getWidth() const
+{
+    return mWidth;
+}
 
-    if (width > 0 && height > 0)
-    {
-        IDirect3DDevice9 *device = mRenderer->getDevice();
-
-        bool requiresInitialization = false;
-
-        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
-        if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
-        {
-            result = device->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat,
-                                                       gl_d3d9::GetMultisampleType(supportedSamples),
-                                                       0, FALSE, &mRenderTarget, NULL);
-        }
-        else
-        {
-            requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != NULL);
-            result = device->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat,
-                                                gl_d3d9::GetMultisampleType(supportedSamples),
-                                                0, FALSE, &mRenderTarget, NULL);
-        }
-
-        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
-        {
-            gl::error(GL_OUT_OF_MEMORY);
-
-            return;
-        }
-
-        ASSERT(SUCCEEDED(result));
-
-        if (requiresInitialization)
-        {
-            // This format requires that the data be initialized before the render target can be used
-            // Unfortunately this requires a Get call on the d3d device but it is far better than having
-            // to mark the render target as lockable and copy data to the gpu.
-            IDirect3DSurface9 *prevRenderTarget = NULL;
-            device->GetRenderTarget(0, &prevRenderTarget);
-            device->SetRenderTarget(0, mRenderTarget);
-            device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0);
-            device->SetRenderTarget(0, prevRenderTarget);
-        }
-    }
+GLsizei TextureRenderTarget9::getHeight() const
+{
+    return mHeight;
+}
 
-    mWidth = width;
-    mHeight = height;
-    mDepth = 1;
-    mInternalFormat = internalFormat;
-    mSamples = supportedSamples;
-    mActualFormat = d3dFormatInfo.internalFormat;
+GLsizei TextureRenderTarget9::getDepth() const
+{
+    return mDepth;
 }
 
-RenderTarget9::~RenderTarget9()
+GLenum TextureRenderTarget9::getInternalFormat() const
 {
-    SafeRelease(mRenderTarget);
+    return mInternalFormat;
 }
 
-RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target)
+GLenum TextureRenderTarget9::getActualFormat() const
 {
-    ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target));
-    return static_cast<rx::RenderTarget9*>(target);
+    return mActualFormat;
 }
 
-void RenderTarget9::invalidate(GLint x, GLint y, GLsizei width, GLsizei height)
+GLsizei TextureRenderTarget9::getSamples() const
 {
-    // Currently a no-op
+    return mSamples;
 }
 
-IDirect3DSurface9 *RenderTarget9::getSurface()
+IDirect3DSurface9 *TextureRenderTarget9::getSurface()
 {
     // Caller is responsible for releasing the returned surface reference.
     // TODO: remove the AddRef to match RenderTarget11
@@ -130,4 +98,51 @@ IDirect3DSurface9 *RenderTarget9::getSurface()
     return mRenderTarget;
 }
 
+
+SurfaceRenderTarget9::SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth)
+    : mSwapChain(swapChain),
+      mDepth(depth)
+{
+}
+
+SurfaceRenderTarget9::~SurfaceRenderTarget9()
+{
+}
+
+GLsizei SurfaceRenderTarget9::getWidth() const
+{
+    return mSwapChain->getWidth();
+}
+
+GLsizei SurfaceRenderTarget9::getHeight() const
+{
+    return mSwapChain->getHeight();
+}
+
+GLsizei SurfaceRenderTarget9::getDepth() const
+{
+    return 1;
+}
+
+GLenum SurfaceRenderTarget9::getInternalFormat() const
+{
+    return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat());
+}
+
+GLenum SurfaceRenderTarget9::getActualFormat() const
+{
+    return d3d9::GetD3DFormatInfo(d3d9::GetTextureFormatInfo(getInternalFormat()).texFormat).internalFormat;
+}
+
+GLsizei SurfaceRenderTarget9::getSamples() const
+{
+    // Our EGL surfaces do not support multisampling.
+    return 0;
+}
+
+IDirect3DSurface9 *SurfaceRenderTarget9::getSurface()
+{
+    return (mDepth ? mSwapChain->getDepthStencil() : mSwapChain->getRenderTarget());
+}
+
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h
index 68d7adb49ef..4585697f4c1 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h
@@ -14,28 +14,74 @@
 
 namespace rx
 {
-class Renderer;
 class Renderer9;
+class SwapChain9;
 
 class RenderTarget9 : public RenderTarget
 {
   public:
-    RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface);
-    RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples);
-    virtual ~RenderTarget9();
+    RenderTarget9() { }
+    virtual ~RenderTarget9() { }
 
     static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget);
 
-    virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height);
+    void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) override;
 
-    IDirect3DSurface9 *getSurface();
+    virtual IDirect3DSurface9 *getSurface() = 0;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(RenderTarget9);
+};
+
+class TextureRenderTarget9 : public RenderTarget9
+{
+  public:
+    TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
+                         GLsizei samples);
+    virtual ~TextureRenderTarget9();
+
+    GLsizei getWidth() const override;
+    GLsizei getHeight() const override;
+    GLsizei getDepth() const override;
+    GLenum getInternalFormat() const override;
+    GLenum getActualFormat() const override;
+    GLsizei getSamples() const override;
+
+    IDirect3DSurface9 *getSurface() override;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(TextureRenderTarget9);
+
+    GLsizei mWidth;
+    GLsizei mHeight;
+    GLsizei mDepth;
+    GLenum mInternalFormat;
+    GLenum mActualFormat;
+    GLsizei mSamples;
 
     IDirect3DSurface9 *mRenderTarget;
+};
+
+class SurfaceRenderTarget9 : public RenderTarget9
+{
+  public:
+    SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth);
+    virtual ~SurfaceRenderTarget9();
+
+    GLsizei getWidth() const override;
+    GLsizei getHeight() const override;
+    GLsizei getDepth() const override;
+    GLenum getInternalFormat() const override;
+    GLenum getActualFormat() const override;
+    GLsizei getSamples() const override;
+
+    IDirect3DSurface9 *getSurface() override;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(SurfaceRenderTarget9);
 
-    Renderer9 *mRenderer;
+    SwapChain9 *mSwapChain;
+    bool mDepth;
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
index d63f9b8582a..601cd24b105 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
@@ -26,6 +26,7 @@
 #include "libGLESv2/renderer/d3d/ShaderD3D.h"
 #include "libGLESv2/renderer/d3d/TextureD3D.h"
 #include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h"
+#include "libGLESv2/renderer/d3d/RenderbufferD3D.h"
 #include "libGLESv2/main.h"
 #include "libGLESv2/Buffer.h"
 #include "libGLESv2/Texture.h"
@@ -33,10 +34,12 @@
 #include "libGLESv2/FramebufferAttachment.h"
 #include "libGLESv2/Renderbuffer.h"
 #include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/State.h"
 #include "libGLESv2/angletypes.h"
 
 #include "libEGL/Display.h"
 
+#include "common/features.h"
 #include "common/utilities.h"
 
 #include <sstream>
@@ -44,14 +47,6 @@
 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
 #define REF_RAST 0
 
-// The "Debug This Pixel..." feature in PIX often fails when using the
-// D3D9Ex interfaces.  In order to get debug pixel to work on a Vista/Win 7
-// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file.
-#if !defined(ANGLE_ENABLE_D3D9EX)
-// Enables use of the IDirect3D9Ex interface, when available
-#define ANGLE_ENABLE_D3D9EX 1
-#endif // !defined(ANGLE_ENABLE_D3D9EX)
-
 #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
 #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
 #endif
@@ -96,8 +91,8 @@ enum
     MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
 };
 
-Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay)
-    : Renderer(display),
+Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes)
+    : RendererD3D(display),
       mDc(hDc)
 {
     mD3d9Module = NULL;
@@ -177,8 +172,8 @@ void Renderer9::release()
 
 Renderer9 *Renderer9::makeRenderer9(Renderer *renderer)
 {
-    ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer));
-    return static_cast<rx::Renderer9*>(renderer);
+    ASSERT(HAS_DYNAMIC_TYPE(Renderer9*, renderer));
+    return static_cast<Renderer9*>(renderer);
 }
 
 EGLint Renderer9::initialize()
@@ -202,7 +197,7 @@ EGLint Renderer9::initialize()
     // Use Direct3D9Ex if available. Among other things, this version is less
     // inclined to report a lost context, for example when the user switches
     // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
-    if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
+    if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
     {
         ASSERT(mD3d9Ex);
         mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
@@ -386,10 +381,13 @@ void Renderer9::initializeDevice()
 
     mSceneStarted = false;
 
-    ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager);
+    ASSERT(!mBlit);
     mBlit = new Blit9(this);
-    mVertexDataManager = new rx::VertexDataManager(this);
-    mIndexDataManager = new rx::IndexDataManager(this);
+    mBlit->initialize();
+
+    ASSERT(!mVertexDataManager && !mIndexDataManager);
+    mVertexDataManager = new VertexDataManager(this);
+    mIndexDataManager = new IndexDataManager(this);
 }
 
 D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
@@ -481,68 +479,92 @@ void Renderer9::endScene()
     }
 }
 
-void Renderer9::sync(bool block)
+gl::Error Renderer9::sync(bool block)
 {
-    HRESULT result;
+    IDirect3DQuery9* query = NULL;
+    gl::Error error = allocateEventQuery(&query);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    IDirect3DQuery9* query = allocateEventQuery();
-    if (!query)
+    HRESULT result = query->Issue(D3DISSUE_END);
+    if (FAILED(result))
     {
-        return;
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result);
     }
 
-    result = query->Issue(D3DISSUE_END);
-    ASSERT(SUCCEEDED(result));
+    // Grab the query data once in blocking and non-blocking case
+    result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
+    if (FAILED(result))
+    {
+        if (d3d9::isDeviceLostError(result))
+        {
+            notifyDeviceLost();
+        }
+
+        freeEventQuery(query);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+    }
 
-    do
+    // If blocking, loop until the query completes
+    while (block && result == S_FALSE)
     {
+        // Keep polling, but allow other threads to do something useful first
+        Sleep(0);
+
         result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
 
-        if(block && result == S_FALSE)
+        // explicitly check for device loss
+        // some drivers seem to return S_FALSE even if the device is lost
+        // instead of D3DERR_DEVICELOST like they should
+        if (result == S_FALSE && testDeviceLost(false))
         {
-            // Keep polling, but allow other threads to do something useful first
-            Sleep(0);
-            // explicitly check for device loss
-            // some drivers seem to return S_FALSE even if the device is lost
-            // instead of D3DERR_DEVICELOST like they should
-            if (testDeviceLost(false))
+            result = D3DERR_DEVICELOST;
+        }
+
+        if (FAILED(result))
+        {
+            if (d3d9::isDeviceLostError(result))
             {
-                result = D3DERR_DEVICELOST;
+                notifyDeviceLost();
             }
+
+            freeEventQuery(query);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
         }
+
     }
-    while(block && result == S_FALSE);
 
     freeEventQuery(query);
 
-    if (d3d9::isDeviceLostError(result))
-    {
-        notifyDeviceLost();
-    }
+    return gl::Error(GL_NO_ERROR);
 }
 
-SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChain *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
 {
-    return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat);
+    return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
 }
 
-IDirect3DQuery9* Renderer9::allocateEventQuery()
+gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery)
 {
-    IDirect3DQuery9 *query = NULL;
-
     if (mEventQueryPool.empty())
     {
-        HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
-        UNUSED_ASSERTION_VARIABLE(result);
-        ASSERT(SUCCEEDED(result));
+        HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, outQuery);
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate event query, result: 0x%X.", result);
+        }
     }
     else
     {
-        query = mEventQueryPool.back();
+        *outQuery = mEventQueryPool.back();
         mEventQueryPool.pop_back();
     }
 
-    return query;
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Renderer9::freeEventQuery(IDirect3DQuery9* query)
@@ -557,14 +579,14 @@ void Renderer9::freeEventQuery(IDirect3DQuery9* query)
     }
 }
 
-IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length)
+gl::Error Renderer9::createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader)
 {
-    return mVertexShaderCache.create(function, length);
+    return mVertexShaderCache.create(function, length, outShader);
 }
 
-IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length)
+gl::Error Renderer9::createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader)
 {
-    return mPixelShaderCache.create(function, length);
+    return mPixelShaderCache.create(function, length, outShader);
 }
 
 HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer)
@@ -604,9 +626,16 @@ QueryImpl *Renderer9::createQuery(GLenum type)
     return new Query9(this, type);
 }
 
-FenceImpl *Renderer9::createFence()
+FenceNVImpl *Renderer9::createFenceNV()
+{
+    return new FenceNV9(this);
+}
+
+FenceSyncImpl *Renderer9::createFenceSync()
 {
-    return new Fence9(this);
+    // Renderer9 doesn't support ES 3.0 and its sync objects.
+    UNREACHABLE();
+    return NULL;
 }
 
 TransformFeedbackImpl* Renderer9::createTransformFeedback()
@@ -620,12 +649,12 @@ bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const
     return false;
 }
 
-bool Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
-                                        GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
+gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+                                             GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
 {
     // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
     UNREACHABLE();
-    return false;
+    return gl::Error(GL_INVALID_OPERATION);
 }
 
 gl::Error Renderer9::generateSwizzle(gl::Texture *texture)
@@ -635,7 +664,7 @@ gl::Error Renderer9::generateSwizzle(gl::Texture *texture)
     return gl::Error(GL_INVALID_OPERATION);
 }
 
-gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
+gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerState)
 {
     std::vector<bool> &forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates;
     std::vector<gl::SamplerState> &appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates;
@@ -645,6 +674,10 @@ gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::
         int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
         int d3dSampler = index + d3dSamplerOffset;
 
+        // Make sure to add the level offset for our tiny compressed texture workaround
+        TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+        DWORD baseLevel = samplerState.baseLevel + textureD3D->getNativeTexture()->getTopLevel();
+
         mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS));
         mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT));
 
@@ -653,7 +686,7 @@ gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::
         gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy);
         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
         mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
-        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.baseLevel);
+        mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, baseLevel);
         if (getRendererExtensions().textureFilterAnisotropic)
         {
             mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy);
@@ -684,7 +717,12 @@ gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *te
         if (texStorage)
         {
             TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage);
-            d3dTexture = storage9->getBaseTexture();
+
+            gl::Error error = storage9->getBaseTexture(&d3dTexture);
+            if (error.isError())
+            {
+                return error;
+            }
         }
         // If we get NULL back from getBaseTexture here, something went wrong
         // in the texture class and we're unexpectedly missing the d3d texture
@@ -751,7 +789,7 @@ gl::Error Renderer9::setRasterizerState(const gl::RasterizerState &rasterState)
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
+gl::Error Renderer9::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
                                    unsigned int sampleMask)
 {
     bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0;
@@ -1097,13 +1135,9 @@ bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count)
 }
 
 
-gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer)
+gl::Error Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, gl::FramebufferAttachment **outColorBuffer)
 {
-    if (!depthbuffer)
-    {
-        ERR("Unexpected null depthbuffer for depth-only FBO.");
-        return NULL;
-    }
+    ASSERT(depthbuffer);
 
     GLsizei width  = depthbuffer->getWidth();
     GLsizei height = depthbuffer->getHeight();
@@ -1116,11 +1150,19 @@ gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachme
             mNullColorbufferCache[i].height == height)
         {
             mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
-            return mNullColorbufferCache[i].buffer;
+            *outColorBuffer = mNullColorbufferCache[i].buffer;
+            return gl::Error(GL_NO_ERROR);
         }
     }
 
-    gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(0, new gl::Colorbuffer(this, width, height, GL_NONE, 0));
+    gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0);
+    gl::Error error = nullRenderbuffer->setStorage(width, height, GL_NONE, 0);
+    if (error.isError())
+    {
+        SafeDelete(nullRenderbuffer);
+        return error;
+    }
+
     gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(GL_NONE, nullRenderbuffer);
 
     // add nullbuffer to the cache
@@ -1139,40 +1181,40 @@ gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachme
     oldest->width = width;
     oldest->height = height;
 
-    return nullbuffer;
+    *outColorBuffer = nullbuffer;
+    return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
+gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer)
 {
     // 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.
     gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0);
     if (!attachment)
     {
-        attachment = getNullColorbuffer(framebuffer->getDepthbuffer());
-    }
-    if (!attachment)
-    {
-        return gl::Error(GL_OUT_OF_MEMORY, "Unable to locate renderbuffer for FBO.");
+        gl::Error error = getNullColorbuffer(framebuffer->getDepthbuffer(), &attachment);
+        if (error.isError())
+        {
+            return error;
+        }
     }
+    ASSERT(attachment);
 
     bool renderTargetChanged = false;
     unsigned int renderTargetSerial = GetAttachmentSerial(attachment);
     if (renderTargetSerial != mAppliedRenderTargetSerial)
     {
         // Apply the render target on the device
-        IDirect3DSurface9 *renderTargetSurface = NULL;
-
-        RenderTarget9 *renderTarget = d3d9::GetAttachmentRenderTarget(attachment);
-        if (renderTarget)
+        RenderTarget9 *renderTarget = NULL;
+        gl::Error error = d3d9::GetAttachmentRenderTarget(attachment, &renderTarget);
+        if (error.isError())
         {
-            renderTargetSurface = renderTarget->getSurface();
+            return error;
         }
+        ASSERT(renderTarget);
 
-        if (!renderTargetSurface)
-        {
-            return gl::Error(GL_OUT_OF_MEMORY, "Internal render target pointer unexpectedly null.");
-        }
+        IDirect3DSurface9 *renderTargetSurface = renderTarget->getSurface();
+        ASSERT(renderTargetSurface);
 
         mDevice->SetRenderTarget(0, renderTargetSurface);
         SafeRelease(renderTargetSurface);
@@ -1204,18 +1246,16 @@ gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
         // Apply the depth stencil on the device
         if (depthStencil)
         {
-            IDirect3DSurface9 *depthStencilSurface = NULL;
-            rx::RenderTarget9 *depthStencilRenderTarget = d3d9::GetAttachmentRenderTarget(depthStencil);
-
-            if (depthStencilRenderTarget)
+            RenderTarget9 *depthStencilRenderTarget = NULL;
+            gl::Error error = d3d9::GetAttachmentRenderTarget(depthStencil, &depthStencilRenderTarget);
+            if (error.isError())
             {
-                depthStencilSurface = depthStencilRenderTarget->getSurface();
+                return error;
             }
+            ASSERT(depthStencilRenderTarget);
 
-            if (!depthStencilSurface)
-            {
-                return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil pointer unexpectedly null.");
-            }
+            IDirect3DSurface9 *depthStencilSurface = depthStencilRenderTarget->getSurface();
+            ASSERT(depthStencilSurface);
 
             mDevice->SetDepthStencilSurface(depthStencilSurface);
             SafeRelease(depthStencilSurface);
@@ -1260,17 +1300,16 @@ gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[],
-                                       GLint first, GLsizei count, GLsizei instances)
+gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances)
 {
     TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
-    gl::Error error = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances);
+    gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances);
     if (error.isError())
     {
         return error;
     }
 
-    return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw);
+    return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, state.getCurrentProgramBinary(), instances, &mRepeatDraw);
 }
 
 // Applies the indices and element array bindings to the Direct3D 9 device
@@ -1296,7 +1335,7 @@ gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *element
     return gl::Error(GL_NO_ERROR);
 }
 
-void Renderer9::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[])
+void Renderer9::applyTransformFeedbackBuffers(const gl::State& state)
 {
     UNREACHABLE();
 }
@@ -1373,10 +1412,15 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi
     // Get the raw indices for an indexed draw
     if (type != GL_NONE && elementArrayBuffer)
     {
-        gl::Buffer *indexBuffer = elementArrayBuffer;
-        BufferImpl *storage = indexBuffer->getImplementation();
+        BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer);
         intptr_t offset = reinterpret_cast<intptr_t>(indices);
-        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+        const uint8_t *bufferData = NULL;
+        gl::Error error = storage->getData(&bufferData);
+        if (error.isError())
+        {
+            return error;
+        }
+        indices = bufferData + offset;
     }
 
     unsigned int startIndex = 0;
@@ -1570,9 +1614,17 @@ gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid
 
     if (elementArrayBuffer)
     {
-        BufferImpl *storage = elementArrayBuffer->getImplementation();
+        BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer);
         intptr_t offset = reinterpret_cast<intptr_t>(indices);
-        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+
+        const uint8_t *bufferData = NULL;
+        gl::Error error = storage->getData(&bufferData);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        indices = bufferData + offset;
     }
 
     switch (type)
@@ -1662,8 +1714,21 @@ gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::Ve
     ASSERT(!transformFeedbackActive);
     ASSERT(!rasterizerDiscard);
 
-    ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout);
-    ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer);
+    ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation());
+
+    ShaderExecutable *vertexExe = NULL;
+    gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ShaderExecutable *pixelExe = NULL;
+    error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe);
+    if (error.isError())
+    {
+        return error;
+    }
 
     IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL);
     IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL);
@@ -1688,7 +1753,7 @@ gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::Ve
     unsigned int programSerial = programBinary->getSerial();
     if (programSerial != mAppliedProgramSerial)
     {
-        programBinary->dirtyAllUniforms();
+        programD3D->dirtyAllUniforms();
         mDxUniformsDirty = true;
         mAppliedProgramSerial = programSerial;
     }
@@ -1696,10 +1761,8 @@ gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::Ve
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Renderer9::applyUniforms(const gl::ProgramBinary &programBinary)
+gl::Error Renderer9::applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray)
 {
-    const std::vector<gl::LinkedUniform*> &uniformArray = programBinary.getUniforms();
-
     for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++)
     {
         gl::LinkedUniform *targetUniform = uniformArray[uniformIndex];
@@ -1797,7 +1860,7 @@ void Renderer9::applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v
     applyUniformnfv(targetUniform, (GLfloat*)vector);
 }
 
-gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
+gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer)
 {
     if (clearParams.colorClearType != GL_FLOAT)
     {
@@ -2219,7 +2282,7 @@ bool Renderer9::isRemovedDeviceResettable() const
 {
     bool success = false;
 
-#ifdef ANGLE_ENABLE_D3D9EX
+#if ANGLE_D3D9EX == ANGLE_ENABLED
     IDirect3D9Ex *d3d9Ex = NULL;
     typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
     Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
@@ -2330,82 +2393,6 @@ int Renderer9::getMaxSwapInterval() const
     return mMaxSwapInterval;
 }
 
-bool Renderer9::copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source)
-{
-    bool result = false;
-
-    if (source && dest)
-    {
-        TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source);
-        TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest);
-
-        int levels = source9->getLevelCount();
-        for (int i = 0; i < levels; ++i)
-        {
-            IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false);
-            IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false);
-
-            result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
-
-            SafeRelease(srcSurf);
-            SafeRelease(dstSurf);
-
-            if (!result)
-            {
-                return false;
-            }
-        }
-    }
-
-    return result;
-}
-
-bool Renderer9::copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source)
-{
-    bool result = false;
-
-    if (source && dest)
-    {
-        TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source);
-        TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest);
-        int levels = source9->getLevelCount();
-        for (int f = 0; f < 6; f++)
-        {
-            for (int i = 0; i < levels; i++)
-            {
-                IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false);
-                IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true);
-
-                result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
-
-                SafeRelease(srcSurf);
-                SafeRelease(dstSurf);
-
-                if (!result)
-                {
-                    return false;
-                }
-            }
-        }
-    }
-
-    return result;
-}
-
-bool Renderer9::copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source)
-{
-    // 3D textures are not available in the D3D9 backend.
-    UNREACHABLE();
-    return false;
-}
-
-bool Renderer9::copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source)
-{
-    // 2D array textures are not supported by the D3D9 backend.
-    UNREACHABLE();
-    return false;
-}
-
 D3DPOOL Renderer9::getBufferPool(DWORD usage) const
 {
     if (mD3d9Ex != NULL)
@@ -2423,8 +2410,8 @@ D3DPOOL Renderer9::getBufferPool(DWORD usage) const
     return D3DPOOL_DEFAULT;
 }
 
-bool Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                            GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
+gl::Error Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                 GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
 {
     RECT rect;
     rect.left = sourceRect.x;
@@ -2435,8 +2422,8 @@ bool Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &s
     return mBlit->copy2D(framebuffer, rect, destFormat, xoffset, yoffset, storage, level);
 }
 
-bool Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                              GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
+gl::Error Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                   GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
 {
     RECT rect;
     rect.left = sourceRect.x;
@@ -2447,24 +2434,26 @@ bool Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle
     return mBlit->copyCube(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level);
 }
 
-bool Renderer9::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                            GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer9::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                 GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
 {
     // 3D textures are not available in the D3D9 backend.
     UNREACHABLE();
-    return false;
+    return gl::Error(GL_INVALID_OPERATION);
 }
 
-bool Renderer9::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                                 GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer9::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                      GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
 {
     // 2D array textures are not available in the D3D9 backend.
     UNREACHABLE();
-    return false;
+    return gl::Error(GL_INVALID_OPERATION);
 }
 
-bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect,
-                         const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter)
+gl::Error Renderer9::blitRect(const gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect,
+                              const gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect,
+                              const gl::Rectangle *scissor, bool blitRenderTarget,
+                              bool blitDepth, bool blitStencil, GLenum filter)
 {
     ASSERT(filter == GL_NEAREST);
 
@@ -2473,35 +2462,33 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
     if (blitRenderTarget)
     {
         gl::FramebufferAttachment *readBuffer = readFramebuffer->getColorbuffer(0);
-        gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getColorbuffer(0);
-        RenderTarget9 *readRenderTarget = NULL;
-        RenderTarget9 *drawRenderTarget = NULL;
-        IDirect3DSurface9* readSurface = NULL;
-        IDirect3DSurface9* drawSurface = NULL;
+        ASSERT(readBuffer);
 
-        if (readBuffer)
-        {
-            readRenderTarget = d3d9::GetAttachmentRenderTarget(readBuffer);
-        }
-        if (drawBuffer)
+        RenderTarget9 *readRenderTarget = NULL;
+        gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readRenderTarget);
+        if (error.isError())
         {
-            drawRenderTarget = d3d9::GetAttachmentRenderTarget(drawBuffer);
+            return error;
         }
+        ASSERT(readRenderTarget);
 
-        if (readRenderTarget)
-        {
-            readSurface = readRenderTarget->getSurface();
-        }
-        if (drawRenderTarget)
-        {
-            drawSurface = drawRenderTarget->getSurface();
-        }
+        gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getColorbuffer(0);
+        ASSERT(drawBuffer);
 
-        if (!readSurface || !drawSurface)
+        RenderTarget9 *drawRenderTarget = NULL;
+        error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget);
+        if (error.isError())
         {
-            ERR("Failed to retrieve the render target.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
+            return error;
         }
+        ASSERT(drawRenderTarget);
+
+        // The getSurface calls do an AddRef so save them until after no errors are possible
+        IDirect3DSurface9* readSurface = readRenderTarget->getSurface();
+        ASSERT(readSurface);
+
+        IDirect3DSurface9* drawSurface = drawRenderTarget->getSurface();
+        ASSERT(drawSurface);
 
         gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
         gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
@@ -2594,43 +2581,40 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
 
         if (FAILED(result))
         {
-            ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
-            return false;
+            return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
         }
     }
 
     if (blitDepth || blitStencil)
     {
         gl::FramebufferAttachment *readBuffer = readFramebuffer->getDepthOrStencilbuffer();
-        gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer();
-        RenderTarget9 *readDepthStencil = NULL;
-        RenderTarget9 *drawDepthStencil = NULL;
-        IDirect3DSurface9* readSurface = NULL;
-        IDirect3DSurface9* drawSurface = NULL;
+        ASSERT(readBuffer);
 
-        if (readBuffer)
-        {
-            readDepthStencil = d3d9::GetAttachmentRenderTarget(readBuffer);
-        }
-        if (drawBuffer)
+        RenderTarget9 *readDepthStencil = NULL;
+        gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readDepthStencil);
+        if (error.isError())
         {
-            drawDepthStencil = d3d9::GetAttachmentRenderTarget(drawBuffer);
+            return error;
         }
+        ASSERT(readDepthStencil);
 
-        if (readDepthStencil)
-        {
-            readSurface = readDepthStencil->getSurface();
-        }
-        if (drawDepthStencil)
-        {
-            drawSurface = drawDepthStencil->getSurface();
-        }
+        gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer();
+        ASSERT(drawBuffer);
 
-        if (!readSurface || !drawSurface)
+        RenderTarget9 *drawDepthStencil = NULL;
+        error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawDepthStencil);
+        if (error.isError())
         {
-            ERR("Failed to retrieve the render target.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
+            return error;
         }
+        ASSERT(drawDepthStencil);
+
+        // The getSurface calls do an AddRef so save them until after no errors are possible
+        IDirect3DSurface9* readSurface = readDepthStencil->getSurface();
+        ASSERT(readDepthStencil);
+
+        IDirect3DSurface9* drawSurface = drawDepthStencil->getSurface();
+        ASSERT(drawDepthStencil);
 
         HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE);
 
@@ -2639,38 +2623,31 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &
 
         if (FAILED(result))
         {
-            ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
-            return false;
+            return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
         }
     }
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+gl::Error Renderer9::readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
                                 GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels)
 {
     ASSERT(pack.pixelBuffer.get() == NULL);
 
-    RenderTarget9 *renderTarget = NULL;
-    IDirect3DSurface9 *surface = NULL;
     gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
+    ASSERT(colorbuffer);
 
-    if (colorbuffer)
-    {
-        renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer);
-    }
-
-    if (renderTarget)
+    RenderTarget9 *renderTarget = NULL;
+    gl::Error error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget);
+    if (error.isError())
     {
-        surface = renderTarget->getSurface();
+        return error;
     }
+    ASSERT(renderTarget);
 
-    if (!surface)
-    {
-        // context must be lost
-        return gl::Error(GL_NO_ERROR);
-    }
+    IDirect3DSurface9 *surface = renderTarget->getSurface();
+    ASSERT(surface);
 
     D3DSURFACE_DESC desc;
     surface->GetDesc(&desc);
@@ -2825,33 +2802,67 @@ gl::Error Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y,
     return gl::Error(GL_NO_ERROR);
 }
 
-RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth)
+gl::Error Renderer9::createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT)
 {
     SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
-    IDirect3DSurface9 *surface = NULL;
-    if (depth)
-    {
-        surface = swapChain9->getDepthStencil();
-    }
-    else
+    *outRT = new SurfaceRenderTarget9(swapChain9, depth);
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT)
+{
+    const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format);
+
+    const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format);
+    GLuint supportedSamples = textureCaps.getNearestSamples(samples);
+
+    IDirect3DSurface9 *renderTarget = NULL;
+    if (width > 0 && height > 0)
     {
-        surface = swapChain9->getRenderTarget();
-    }
+        bool requiresInitialization = false;
+        HRESULT result = D3DERR_INVALIDCALL;
+
+        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
+        if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+        {
+            result = mDevice->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat,
+                                                        gl_d3d9::GetMultisampleType(supportedSamples),
+                                                        0, FALSE, &renderTarget, NULL);
+        }
+        else
+        {
+            requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != NULL);
+            result = mDevice->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat,
+                                                 gl_d3d9::GetMultisampleType(supportedSamples),
+                                                 0, FALSE, &renderTarget, NULL);
+        }
 
-    RenderTarget9 *renderTarget = new RenderTarget9(this, surface);
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target, result: 0x%X.", result);
+        }
 
-    return renderTarget;
-}
+        if (requiresInitialization)
+        {
+            // This format requires that the data be initialized before the render target can be used
+            // Unfortunately this requires a Get call on the d3d device but it is far better than having
+            // to mark the render target as lockable and copy data to the gpu.
+            IDirect3DSurface9 *prevRenderTarget = NULL;
+            mDevice->GetRenderTarget(0, &prevRenderTarget);
+            mDevice->SetRenderTarget(0, renderTarget);
+            mDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0);
+            mDevice->SetRenderTarget(0, prevRenderTarget);
+        }
+    }
 
-RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples)
-{
-    RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples);
-    return renderTarget;
+    *outRT = new TextureRenderTarget9(renderTarget, format, width, height, 1, supportedSamples);
+    return gl::Error(GL_NO_ERROR);
 }
 
-ShaderImpl *Renderer9::createShader(GLenum type)
+ShaderImpl *Renderer9::createShader(const gl::Data &data, GLenum type)
 {
-    return new ShaderD3D(type, this);
+    return new ShaderD3D(data, type, this);
 }
 
 ProgramImpl *Renderer9::createProgram()
@@ -2864,64 +2875,69 @@ void Renderer9::releaseShaderCompiler()
     ShaderD3D::releaseCompiler();
 }
 
-ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type,
-                                            const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
-                                            bool separatedOutputBuffers)
+gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderType type,
+                                    const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+                                    bool separatedOutputBuffers, ShaderExecutable **outExecutable)
 {
     // Transform feedback is not supported in ES2 or D3D9
     ASSERT(transformFeedbackVaryings.size() == 0);
 
-    ShaderExecutable9 *executable = NULL;
-
     switch (type)
     {
-      case rx::SHADER_VERTEX:
+      case SHADER_VERTEX:
         {
-            IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length);
-            if (vshader)
+            IDirect3DVertexShader9 *vshader = NULL;
+            gl::Error error = createVertexShader((DWORD*)function, length, &vshader);
+            if (error.isError())
             {
-                executable = new ShaderExecutable9(function, length, vshader);
+                return error;
             }
+            *outExecutable = new ShaderExecutable9(function, length, vshader);
         }
         break;
-      case rx::SHADER_PIXEL:
+      case SHADER_PIXEL:
         {
-            IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length);
-            if (pshader)
+            IDirect3DPixelShader9 *pshader = NULL;
+            gl::Error error = createPixelShader((DWORD*)function, length, &pshader);
+            if (error.isError())
             {
-                executable = new ShaderExecutable9(function, length, pshader);
+                return error;
             }
+            *outExecutable = new ShaderExecutable9(function, length, pshader);
         }
         break;
       default:
         UNREACHABLE();
-        break;
+        return gl::Error(GL_INVALID_OPERATION);
     }
 
-    return executable;
+    return gl::Error(GL_NO_ERROR);
 }
 
-ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
-                                                 const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
-                                                 bool separatedOutputBuffers, D3DWorkaroundType workaround)
+gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
+                                         const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+                                         bool separatedOutputBuffers, D3DWorkaroundType workaround,
+                                         ShaderExecutable **outExectuable)
 {
     // Transform feedback is not supported in ES2 or D3D9
     ASSERT(transformFeedbackVaryings.size() == 0);
 
-    const char *profile = NULL;
-
+    const char *profileType = NULL;
     switch (type)
     {
-      case rx::SHADER_VERTEX:
-        profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0";
+      case SHADER_VERTEX:
+        profileType = "vs";
         break;
-      case rx::SHADER_PIXEL:
-        profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0";
+      case SHADER_PIXEL:
+        profileType = "ps";
         break;
       default:
         UNREACHABLE();
-        return NULL;
+        return gl::Error(GL_INVALID_OPERATION);
     }
+    unsigned int profileMajorVersion = (getMajorShaderModel() >= 3) ? 3 : 2;
+    unsigned int profileMinorVersion = 0;
+    std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
 
     UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL;
 
@@ -2942,49 +2958,54 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const cha
 #endif
 
         flags |= D3DCOMPILE_DEBUG;
-
-        std::string sourcePath = getTempPath();
-        std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL);
-        writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
     }
 
     // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
     // Try the default flags first and if compilation fails, try some alternatives.
-    const UINT extraFlags[] =
+    std::vector<CompileConfig> configs;
+    configs.push_back(CompileConfig(flags,                                  "default"            ));
+    configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL,  "avoid flow control" ));
+    configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control"));
+
+    ID3DBlob *binary = NULL;
+    std::string debugInfo;
+    gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, NULL, &binary, &debugInfo);
+    if (error.isError())
     {
-        flags,
-        flags | D3DCOMPILE_AVOID_FLOW_CONTROL,
-        flags | D3DCOMPILE_PREFER_FLOW_CONTROL
-    };
+        return error;
+    }
 
-    const static char *extraFlagNames[] =
+    // It's possible that binary is NULL if the compiler failed in all configurations.  Set the executable to NULL
+    // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK.
+    if (!binary)
     {
-        "default",
-        "avoid flow control",
-        "prefer flow control"
-    };
+        *outExectuable = NULL;
+        return gl::Error(GL_NO_ERROR);
+    }
 
-    int attempts = ArraySize(extraFlags);
+    error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
+                           transformFeedbackVaryings, separatedOutputBuffers, outExectuable);
 
-    ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts);
-    if (!binary)
+    SafeRelease(binary);
+    if (error.isError())
     {
-        return NULL;
+        return error;
     }
 
-    ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
-                                                  transformFeedbackVaryings, separatedOutputBuffers);
-    SafeRelease(binary);
+    if (!debugInfo.empty())
+    {
+        (*outExectuable)->appendDebugInfo(debugInfo);
+    }
 
-    return executable;
+    return gl::Error(GL_NO_ERROR);
 }
 
-rx::UniformStorage *Renderer9::createUniformStorage(size_t storageSize)
+UniformStorage *Renderer9::createUniformStorage(size_t storageSize)
 {
     return new UniformStorage(storageSize);
 }
 
-bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
+gl::Error Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
 {
     return mBlit->boxFilter(source, dest);
 }
@@ -3006,41 +3027,40 @@ D3DPOOL Renderer9::getTexturePool(DWORD usage) const
     return D3DPOOL_DEFAULT;
 }
 
-bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
+gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
 {
-    if (source && dest)
-    {
-        HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
+    ASSERT(source && dest);
 
-        if (fromManaged)
-        {
-            D3DSURFACE_DESC desc;
-            source->GetDesc(&desc);
+    HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
 
-            IDirect3DSurface9 *surf = 0;
-            result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
+    if (fromManaged)
+    {
+        D3DSURFACE_DESC desc;
+        source->GetDesc(&desc);
 
-            if (SUCCEEDED(result))
-            {
-                Image9::copyLockableSurfaces(surf, source);
-                result = mDevice->UpdateSurface(surf, NULL, dest, NULL);
-                SafeRelease(surf);
-            }
-        }
-        else
-        {
-            endScene();
-            result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
-        }
+        IDirect3DSurface9 *surf = 0;
+        result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
 
-        if (FAILED(result))
+        if (SUCCEEDED(result))
         {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            return false;
+            Image9::copyLockableSurfaces(surf, source);
+            result = mDevice->UpdateSurface(surf, NULL, dest, NULL);
+            SafeRelease(surf);
         }
     }
+    else
+    {
+        endScene();
+        result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
+    }
 
-    return true;
+    if (FAILED(result))
+    {
+        ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit internal texture, result: 0x%X.", result);
+    }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 Image *Renderer9::createImage()
@@ -3048,11 +3068,11 @@ Image *Renderer9::createImage()
     return new Image9();
 }
 
-void Renderer9::generateMipmap(Image *dest, Image *src)
+gl::Error Renderer9::generateMipmap(Image *dest, Image *src)
 {
     Image9 *src9 = Image9::makeImage9(src);
     Image9 *dst9 = Image9::makeImage9(dest);
-    Image9::generateMipmap(dst9, src9);
+    return Image9::generateMipmap(dst9, src9);
 }
 
 TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain)
@@ -3099,6 +3119,19 @@ TextureImpl *Renderer9::createTexture(GLenum target)
     return NULL;
 }
 
+RenderbufferImpl *Renderer9::createRenderbuffer()
+{
+    RenderbufferD3D *renderbuffer = new RenderbufferD3D(this);
+    return renderbuffer;
+}
+
+RenderbufferImpl *Renderer9::createRenderbuffer(SwapChain *swapChain, bool depth)
+{
+    RenderbufferD3D *renderbuffer = new RenderbufferD3D(this);
+    renderbuffer->setStorage(swapChain, depth);
+    return renderbuffer;
+}
+
 bool Renderer9::getLUID(LUID *adapterLuid) const
 {
     adapterLuid->HighPart = 0;
@@ -3113,7 +3146,7 @@ bool Renderer9::getLUID(LUID *adapterLuid) const
     return false;
 }
 
-rx::VertexConversionType Renderer9::getVertexConversionType(const gl::VertexFormat &vertexFormat) const
+VertexConversionType Renderer9::getVertexConversionType(const gl::VertexFormat &vertexFormat) const
 {
     return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).conversionType;
 }
@@ -3128,4 +3161,9 @@ void Renderer9::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCa
     d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, outExtensions);
 }
 
+Workarounds Renderer9::generateWorkarounds() const
+{
+    return d3d9::GenerateWorkarounds();
+}
+
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
index dd5f30268a7..10d2fb11e8d 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
@@ -11,10 +11,10 @@
 
 #include "common/angleutils.h"
 #include "common/mathutil.h"
-#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
 #include "libGLESv2/renderer/d3d/d3d9/ShaderCache.h"
 #include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h"
-#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
+#include "libGLESv2/renderer/d3d/RendererD3D.h"
 #include "libGLESv2/renderer/RenderTarget.h"
 
 namespace gl
@@ -22,6 +22,11 @@ namespace gl
 class FramebufferAttachment;
 }
 
+namespace egl
+{
+class AttributeMap;
+}
+
 namespace rx
 {
 class VertexDataManager;
@@ -31,10 +36,10 @@ class StaticIndexBufferInterface;
 struct TranslatedAttribute;
 class Blit9;
 
-class Renderer9 : public Renderer
+class Renderer9 : public RendererD3D
 {
   public:
-    Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay);
+    Renderer9(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes);
     virtual ~Renderer9();
 
     static Renderer9 *makeRenderer9(Renderer *renderer);
@@ -48,27 +53,27 @@ class Renderer9 : public Renderer
     void startScene();
     void endScene();
 
-    virtual void sync(bool block);
+    virtual gl::Error sync(bool block);
 
-    virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
+    virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
 
-    IDirect3DQuery9* allocateEventQuery();
+    gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery);
     void freeEventQuery(IDirect3DQuery9* query);
 
     // resource creation
-    IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length);
-    IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length);
+    gl::Error createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader);
+    gl::Error createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader);
     HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer);
     HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer);
     virtual gl::Error generateSwizzle(gl::Texture *texture);
-    virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
+    virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler);
     virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture);
 
     virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]);
 
     virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
-    virtual gl::Error setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
-                                    unsigned int sampleMask);
+    gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
+                            unsigned int sampleMask) override;
     virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
                                            int stencilBackRef, bool frontFaceCCW);
 
@@ -76,35 +81,35 @@ class Renderer9 : public Renderer
     virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
                              bool ignoreViewport);
 
-    virtual gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer);
+    gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override;
     virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
                                    bool rasterizerDiscard, bool transformFeedbackActive);
-    virtual gl::Error applyUniforms(const gl::ProgramBinary &programBinary);
+    virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray);
     virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount);
-    virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[],
-                                        GLint first, GLsizei count, GLsizei instances);
+    virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances);
     virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
 
-    virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]);
+    virtual void applyTransformFeedbackBuffers(const gl::State& state);
 
     virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive);
     virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
                                    gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
 
-    virtual gl::Error clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
+    gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) override;
 
     virtual void markAllStateDirty();
 
     // lost device
-    void notifyDeviceLost();
-    virtual bool isDeviceLost();
-    virtual bool testDeviceLost(bool notify);
-    virtual bool testDeviceResettable();
+    void notifyDeviceLost() override;
+    bool isDeviceLost() override;
+    bool testDeviceLost(bool notify) override;
+    bool testDeviceResettable() override;
+
+    DWORD getAdapterVendor() const override;
+    std::string getRendererDescription() const override;
+    GUID getAdapterIdentifier() const override;
 
     IDirect3DDevice9 *getDevice() { return mDevice; }
-    virtual DWORD getAdapterVendor() const;
-    virtual std::string getRendererDescription() const;
-    virtual GUID getAdapterIdentifier() const;
 
     virtual unsigned int getReservedVertexUniformVectors() const;
     virtual unsigned int getReservedFragmentUniformVectors() const;
@@ -119,47 +124,45 @@ class Renderer9 : public Renderer
     virtual int getMaxSwapInterval() const;
 
     // Pixel operations
-    virtual bool copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source);
-    virtual bool copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source);
-    virtual bool copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source);
-    virtual bool copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source);
-
-    virtual bool copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                             GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level);
-    virtual bool copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                               GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level);
-    virtual bool copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                             GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
-    virtual bool copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+    virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                  GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level);
+    virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                    GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level);
+    virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
                                   GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
+    virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                       GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
 
-    virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
-                          const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter);
+    gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect,
+                       const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
+                       const gl::Rectangle *scissor, bool blitRenderTarget,
+                       bool blitDepth, bool blitStencil, GLenum filter) override;
 
-    virtual gl::Error readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+    virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
                                  GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
 
     // RenderTarget creation
-    virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth);
-    virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples);
+    virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT);
+    virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT);
 
     // Shader creation
-    virtual ShaderImpl *createShader(GLenum type);
+    virtual ShaderImpl *createShader(const gl::Data &data, GLenum type);
     virtual ProgramImpl *createProgram();
 
     // Shader operations
-    virtual void releaseShaderCompiler();
-    virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
-                                             const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
-                                             bool separatedOutputBuffers);
-    virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
-                                                  const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
-                                                  bool separatedOutputBuffers, D3DWorkaroundType workaround);
+    void releaseShaderCompiler() override;
+    virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type,
+                                     const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+                                     bool separatedOutputBuffers, ShaderExecutable **outExecutable);
+    virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
+                                          const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+                                          bool separatedOutputBuffers, D3DWorkaroundType workaround,
+                                          ShaderExecutable **outExectuable);
     virtual UniformStorage *createUniformStorage(size_t storageSize);
 
     // Image operations
     virtual Image *createImage();
-    virtual void generateMipmap(Image *dest, Image *source);
+    gl::Error generateMipmap(Image *dest, Image *source) override;
     virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
     virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
     virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels);
@@ -169,6 +172,10 @@ class Renderer9 : public Renderer
     // Texture creation
     virtual TextureImpl *createTexture(GLenum target);
 
+    // Renderbuffer creation
+    virtual RenderbufferImpl *createRenderbuffer();
+    virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth);
+
     // Buffer creation
     virtual BufferImpl *createBuffer();
     virtual VertexBuffer *createVertexBuffer();
@@ -179,29 +186,33 @@ class Renderer9 : public Renderer
 
     // Query and Fence creation
     virtual QueryImpl *createQuery(GLenum type);
-    virtual FenceImpl *createFence();
+    virtual FenceNVImpl *createFenceNV();
+    virtual FenceSyncImpl *createFenceSync();
 
     // Transform Feedback creation
     virtual TransformFeedbackImpl* createTransformFeedback();
 
     // Buffer-to-texture and Texture-to-buffer copies
     virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const;
-    virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
-                                         GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
+    virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+                                              GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
 
     // D3D9-renderer specific methods
-    bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
+    gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
 
     D3DPOOL getTexturePool(DWORD usage) const;
 
     virtual bool getLUID(LUID *adapterLuid) const;
-    virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const;
+    virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const;
     virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const;
 
+    gl::Error copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
+
   private:
     DISALLOW_COPY_AND_ASSIGN(Renderer9);
 
-    virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const;
+    void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override;
+    Workarounds generateWorkarounds() const override;
 
     void release();
 
@@ -214,8 +225,7 @@ class Renderer9 : public Renderer
 
     gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB);
 
-    bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
-    gl::FramebufferAttachment *getNullColorbuffer(gl::FramebufferAttachment *depthbuffer);
+    gl::Error getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, gl::FramebufferAttachment **outColorBuffer);
 
     D3DPOOL getBufferPool(DWORD usage) const;
 
@@ -263,7 +273,7 @@ class Renderer9 : public Renderer
     unsigned int mAppliedStencilbufferSerial;
     bool mDepthStencilInitialized;
     bool mRenderTargetDescInitialized;
-    rx::RenderTarget::Desc mRenderTargetDesc;
+    RenderTarget::Desc mRenderTargetDesc;
     unsigned int mCurStencilSize;
     unsigned int mCurDepthSize;
 
@@ -310,8 +320,8 @@ class Renderer9 : public Renderer
     IDirect3DPixelShader9 *mAppliedPixelShader;
     unsigned int mAppliedProgramSerial;
 
-    rx::dx_VertexConstants mVertexConstants;
-    rx::dx_PixelConstants mPixelConstants;
+    dx_VertexConstants mVertexConstants;
+    dx_PixelConstants mPixelConstants;
     bool mDxUniformsDirty;
 
     // A pool of event queries that are currently unused.
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h
index 2ad30228398..6d7d2d648f0 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h
@@ -10,6 +10,8 @@
 #ifndef LIBGLESV2_RENDERER_SHADER_CACHE_H_
 #define LIBGLESV2_RENDERER_SHADER_CACHE_H_
 
+#include "libGLESv2/Error.h"
+
 #include "common/debug.h"
 
 #include <cstddef>
@@ -37,21 +39,22 @@ class ShaderCache
         mDevice = device;
     }
 
-    ShaderObject *create(const DWORD *function, size_t length)
+    gl::Error create(const DWORD *function, size_t length, ShaderObject **outShaderObject)
     {
         std::string key(reinterpret_cast<const char*>(function), length);
         typename Map::iterator it = mMap.find(key);
         if (it != mMap.end())
         {
             it->second->AddRef();
-            return it->second;
+            *outShaderObject = it->second;
+            return gl::Error(GL_NO_ERROR);
         }
 
         ShaderObject *shader;
         HRESULT result = createShader(function, &shader);
         if (FAILED(result))
         {
-            return NULL;
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader, result: 0x%X.", result);
         }
 
         // Random eviction policy.
@@ -64,7 +67,8 @@ class ShaderCache
         shader->AddRef();
         mMap[key] = shader;
 
-        return shader;
+        *outShaderObject = shader;
+        return gl::Error(GL_NO_ERROR);
     }
 
     void clear()
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp
index 0aeaabb1caf..95eb1a4371f 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp
@@ -11,12 +11,15 @@
 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
 #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
 
+#include "common/features.h"
+
 namespace rx
 {
 
-SwapChain9::SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle,
+SwapChain9::SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
                        GLenum backBufferFormat, GLenum depthBufferFormat)
-    : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
+    : mRenderer(renderer),
+      SwapChain(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat)
 {
     mSwapChain = NULL;
     mBackBuffer = NULL;
@@ -41,7 +44,7 @@ void SwapChain9::release()
     SafeRelease(mRenderTarget);
     SafeRelease(mOffscreenTexture);
 
-    if (mWindow)
+    if (mNativeWindow.getNativeWindow())
     {
         mShareHandle = NULL;
     }
@@ -49,7 +52,7 @@ void SwapChain9::release()
 
 static DWORD convertInterval(EGLint interval)
 {
-#ifdef ANGLE_FORCE_VSYNC_OFF
+#if ANGLE_VSYNC == ANGLE_DISABLED
     return D3DPRESENT_INTERVAL_IMMEDIATE;
 #else
     switch(interval)
@@ -95,7 +98,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
     SafeRelease(mDepthStencil);
 
     HANDLE *pShareHandle = NULL;
-    if (!mWindow && mRenderer->getShareHandleSupport())
+    if (!mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport())
     {
         pShareHandle = &mShareHandle;
     }
@@ -152,7 +155,8 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
 
     const d3d9::TextureFormat &depthBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mDepthBufferFormat);
 
-    if (mWindow)
+    EGLNativeWindowType window = mNativeWindow.getNativeWindow();
+    if (window)
     {
         D3DPRESENT_PARAMETERS presentParameters = {0};
         presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat;
@@ -160,7 +164,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
         presentParameters.BackBufferFormat = backBufferd3dFormatInfo.renderFormat;
         presentParameters.EnableAutoDepthStencil = FALSE;
         presentParameters.Flags = 0;
-        presentParameters.hDeviceWindow = mWindow;
+        presentParameters.hDeviceWindow = window;
         presentParameters.MultiSampleQuality = 0;                  // FIXME: Unimplemented
         presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;   // FIXME: Unimplemented
         presentParameters.PresentationInterval = convertInterval(swapInterval);
@@ -203,7 +207,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
 
         result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
         ASSERT(SUCCEEDED(result));
-        InvalidateRect(mWindow, NULL, FALSE);
+        InvalidateRect(window, NULL, FALSE);
     }
 
     if (mDepthBufferFormat != GL_NONE)
@@ -238,7 +242,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
 }
 
 // parameters should be validated/clamped by caller
-EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint)
+EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
 {
     if (!mSwapChain)
     {
@@ -379,8 +383,8 @@ IDirect3DTexture9 *SwapChain9::getOffscreenTexture()
 
 SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain)
 {
-    ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain9*, swapChain));
-    return static_cast<rx::SwapChain9*>(swapChain);
+    ASSERT(HAS_DYNAMIC_TYPE(SwapChain9*, swapChain));
+    return static_cast<SwapChain9*>(swapChain);
 }
 
 void SwapChain9::recreate()
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h
index 4d756f80d12..cb33bfbc0c5 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h
@@ -19,19 +19,22 @@ class Renderer9;
 class SwapChain9 : public SwapChain
 {
   public:
-    SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle,
+    SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
                GLenum backBufferFormat, GLenum depthBufferFormat);
     virtual ~SwapChain9();
 
     EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
     virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
-    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint);
+    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
     virtual void recreate();
 
     virtual IDirect3DSurface9 *getRenderTarget();
     virtual IDirect3DSurface9 *getDepthStencil();
     virtual IDirect3DTexture9 *getOffscreenTexture();
 
+    EGLint getWidth() const { return mWidth; }
+    EGLint getHeight() const { return mHeight; }
+
     static SwapChain9 *makeSwapChain9(SwapChain *swapChain);
 
   private:
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp
index f44e33db184..0ff4fd3b0f2 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp
@@ -20,8 +20,13 @@
 
 namespace rx
 {
-TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage)
+TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage)
     : mTopLevel(0),
+      mMipLevels(0),
+      mTextureWidth(0),
+      mTextureHeight(0),
+      mInternalFormat(GL_NONE),
+      mTextureFormat(D3DFMT_UNKNOWN),
       mRenderer(Renderer9::makeRenderer9(renderer)),
       mD3DUsage(usage),
       mD3DPool(mRenderer->getTexturePool(usage))
@@ -84,44 +89,52 @@ int TextureStorage9::getTopLevel() const
 
 int TextureStorage9::getLevelCount() const
 {
-    return getBaseTexture() ? (getBaseTexture()->GetLevelCount() - getTopLevel()) : 0;
+    return mMipLevels - mTopLevel;
 }
 
-TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain)
+gl::Error TextureStorage9::setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type,
+                                   const gl::PixelUnpackState &unpack, const uint8_t *pixelData)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain)
     : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET)
 {
     IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture();
     mTexture = surfaceTexture;
+    mMipLevels = surfaceTexture->GetLevelCount();
+
+    mInternalFormat = swapchain->GetBackBufferInternalFormat();
+
+    D3DSURFACE_DESC surfaceDesc;
+    surfaceTexture->GetLevelDesc(0, &surfaceDesc);
+    mTextureWidth = surfaceDesc.Width;
+    mTextureHeight = surfaceDesc.Height;
+    mTextureFormat = surfaceDesc.Format;
+
     mRenderTarget = NULL;
 
-    initializeRenderTarget();
     initializeSerials(1, 1);
 }
 
-TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
+TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
     : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
 {
     mTexture = NULL;
     mRenderTarget = NULL;
-    // 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
-    if (width > 0 && height > 0)
-    {
-        IDirect3DDevice9 *device = mRenderer->getDevice();
-        const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
-        d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel);
-        UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels;
 
-        HRESULT result = device->CreateTexture(width, height, creationLevels, getUsage(), d3dFormatInfo.texFormat, getPool(), &mTexture, NULL);
+    mInternalFormat = internalformat;
 
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
+    const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+    mTextureFormat = d3dFormatInfo.texFormat;
+
+    d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel);
+    mTextureWidth = width;
+    mTextureHeight = height;
+    mMipLevels = mTopLevel + levels;
 
-    initializeRenderTarget();
     initializeSerials(getLevelCount(), 1);
 }
 
@@ -139,104 +152,168 @@ TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *s
 
 // Increments refcount on surface.
 // caller must Release() the returned surface
-IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty)
+gl::Error TextureStorage9_2D::getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface)
 {
-    IDirect3DSurface9 *surface = NULL;
+    IDirect3DBaseTexture9 *baseTexture = NULL;
+    gl::Error error = getBaseTexture(&baseTexture);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    IDirect3DTexture9 *texture = static_cast<IDirect3DTexture9*>(baseTexture);
 
-    if (mTexture)
+    HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface);
+
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
     {
-        HRESULT result = mTexture->GetSurfaceLevel(level + mTopLevel, &surface);
-        UNUSED_ASSERTION_VARIABLE(result);
-        ASSERT(SUCCEEDED(result));
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
+    }
 
-        // With managed textures the driver needs to be informed of updates to the lower mipmap levels
-        if (level + mTopLevel != 0 && isManaged() && dirty)
+    // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+    if (level + mTopLevel != 0 && isManaged() && dirty)
+    {
+        texture->AddDirtyRect(NULL);
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, RenderTarget **outRT)
+{
+    if (!mRenderTarget && isRenderTarget())
+    {
+        IDirect3DSurface9 *surface = NULL;
+        gl::Error error = getSurfaceLevel(0, false, &surface);
+        if (error.isError())
         {
-            mTexture->AddDirtyRect(NULL);
+            return error;
         }
+
+        mRenderTarget = new TextureRenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 0);
     }
 
-    return surface;
+    ASSERT(outRT);
+    *outRT = mRenderTarget;
+    return gl::Error(GL_NO_ERROR);
 }
 
-RenderTarget *TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/)
+gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
 {
-    return mRenderTarget;
+    IDirect3DSurface9 *upper = NULL;
+    gl::Error error = getSurfaceLevel(sourceIndex.mipIndex, false, &upper);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    IDirect3DSurface9 *lower = NULL;
+    error = getSurfaceLevel(destIndex.mipIndex, true, &lower);
+    if (error.isError())
+    {
+        SafeRelease(upper);
+        return error;
+    }
+
+    ASSERT(upper && lower);
+    error = mRenderer->boxFilter(upper, lower);
+
+    SafeRelease(upper);
+    SafeRelease(lower);
+
+    return error;
 }
 
-void TextureStorage9_2D::generateMipmaps()
+gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
 {
-    // Base level must already be defined
-
-    for (int level = 1; level < getLevelCount(); level++)
+    // 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
+    if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
     {
-        IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false);
-        IDirect3DSurface9 *lower = getSurfaceLevel(level, true);
+        ASSERT(mMipLevels > 0);
 
-        if (upper != NULL && lower != NULL)
+        IDirect3DDevice9 *device = mRenderer->getDevice();
+        HRESULT result = device->CreateTexture(mTextureWidth, mTextureHeight, mMipLevels, getUsage(), mTextureFormat,
+                                               getPool(), &mTexture, NULL);
+
+        if (FAILED(result))
         {
-            mRenderer->boxFilter(upper, lower);
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D storage texture, result: 0x%X.", result);
         }
-
-        SafeRelease(upper);
-        SafeRelease(lower);
     }
-}
 
-IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const
-{
-    return mTexture;
+    *outTexture = mTexture;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureStorage9_2D::initializeRenderTarget()
+gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage)
 {
-    ASSERT(mRenderTarget == NULL);
+    ASSERT(destStorage);
+
+    TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(destStorage);
 
-    if (mTexture != NULL && isRenderTarget())
+    int levels = getLevelCount();
+    for (int i = 0; i < levels; ++i)
     {
-        IDirect3DSurface9 *surface = getSurfaceLevel(0, false);
+        IDirect3DSurface9 *srcSurf = NULL;
+        gl::Error error = getSurfaceLevel(i, false, &srcSurf);
+        if (error.isError())
+        {
+            return error;
+        }
 
-        mRenderTarget = new RenderTarget9(mRenderer, surface);
+        IDirect3DSurface9 *dstSurf = NULL;
+        error = dest9->getSurfaceLevel(i, true, &dstSurf);
+        if (error.isError())
+        {
+            SafeRelease(srcSurf);
+            return error;
+        }
+
+        error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged());
+
+        SafeRelease(srcSurf);
+        SafeRelease(dstSurf);
+
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
+TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
     : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
 {
     mTexture = NULL;
-    for (int i = 0; i < 6; ++i)
+    for (int i = 0; i < CUBE_FACE_COUNT; ++i)
     {
         mRenderTarget[i] = NULL;
     }
 
-    // if the size is not positive this should be treated as an incomplete texture
-    // we handle that here by skipping the d3d texture creation
-    if (size > 0)
-    {
-        IDirect3DDevice9 *device = mRenderer->getDevice();
-        int height = size;
-        const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
-        d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel);
-        UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels;
+    mInternalFormat = internalformat;
 
-        HRESULT result = device->CreateCubeTexture(size, creationLevels, getUsage(), d3dFormatInfo.texFormat, getPool(), &mTexture, NULL);
+    const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+    mTextureFormat = d3dFormatInfo.texFormat;
 
-        if (FAILED(result))
-        {
-            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-            gl::error(GL_OUT_OF_MEMORY);
-        }
-    }
+    int height = size;
+    d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel);
+    mTextureWidth = size;
+    mTextureHeight = size;
+    mMipLevels = mTopLevel + levels;
 
-    initializeRenderTarget();
-    initializeSerials(getLevelCount() * 6, 6);
+    initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT);
 }
 
 TextureStorage9_Cube::~TextureStorage9_Cube()
 {
     SafeRelease(mTexture);
 
-    for (int i = 0; i < 6; ++i)
+    for (int i = 0; i < CUBE_FACE_COUNT; ++i)
     {
         SafeDelete(mRenderTarget[i]);
     }
@@ -250,74 +327,146 @@ TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStor
 
 // Increments refcount on surface.
 // caller must Release() the returned surface
-IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty)
+gl::Error TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface)
 {
-    IDirect3DSurface9 *surface = NULL;
+    IDirect3DBaseTexture9 *baseTexture = NULL;
+    gl::Error error = getBaseTexture(&baseTexture);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    IDirect3DCubeTexture9 *texture = static_cast<IDirect3DCubeTexture9*>(baseTexture);
 
-    if (mTexture)
+    D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget);
+    HRESULT result = texture->GetCubeMapSurface(face, level + mTopLevel, outSurface);
+
+    ASSERT(SUCCEEDED(result));
+    if (FAILED(result))
     {
-        D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget);
-        HRESULT result = mTexture->GetCubeMapSurface(face, level + mTopLevel, &surface);
-        UNUSED_ASSERTION_VARIABLE(result);
-        ASSERT(SUCCEEDED(result));
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
+    }
 
-        // With managed textures the driver needs to be informed of updates to the lower mipmap levels
-        if (level != 0 && isManaged() && dirty)
+    // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+    if (level != 0 && isManaged() && dirty)
+    {
+        texture->AddDirtyRect(face, NULL);
+    }
+
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
+{
+    ASSERT(outRT);
+    ASSERT(index.mipIndex == 0);
+    ASSERT(index.layerIndex >= 0 && index.layerIndex < CUBE_FACE_COUNT);
+
+    if (mRenderTarget[index.layerIndex] == NULL && isRenderTarget())
+    {
+        IDirect3DSurface9 *surface = NULL;
+        gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex, 0, false, &surface);
+        if (error.isError())
         {
-            mTexture->AddDirtyRect(face, NULL);
+            return error;
         }
+
+        mRenderTarget[index.layerIndex] = new TextureRenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 0);
     }
 
-    return surface;
+    *outRT = mRenderTarget[index.layerIndex];
+    return gl::Error(GL_NO_ERROR);
 }
 
-RenderTarget *TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index)
+gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
 {
-    return mRenderTarget[index.layerIndex];
+    IDirect3DSurface9 *upper = NULL;
+    gl::Error error = getCubeMapSurface(sourceIndex.type, sourceIndex.mipIndex, false, &upper);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    IDirect3DSurface9 *lower = NULL;
+    error = getCubeMapSurface(destIndex.type, destIndex.mipIndex, true, &lower);
+    if (error.isError())
+    {
+        SafeRelease(upper);
+        return error;
+    }
+
+    ASSERT(upper && lower);
+    error = mRenderer->boxFilter(upper, lower);
+
+    SafeRelease(upper);
+    SafeRelease(lower);
+
+    return error;
 }
 
-void TextureStorage9_Cube::generateMipmaps()
+gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
 {
-    // Base level must already be defined
-
-    for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+    // if the size is not positive this should be treated as an incomplete texture
+    // we handle that here by skipping the d3d texture creation
+    if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
     {
-        for (int level = 1; level < getLevelCount(); level++)
-        {
-            IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1, false);
-            IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, true);
+        ASSERT(mMipLevels > 0);
+        ASSERT(mTextureWidth == mTextureHeight);
 
-            if (upper != NULL && lower != NULL)
-            {
-                mRenderer->boxFilter(upper, lower);
-            }
+        IDirect3DDevice9 *device = mRenderer->getDevice();
+        HRESULT result = device->CreateCubeTexture(mTextureWidth, mMipLevels, getUsage(), mTextureFormat, getPool(),
+                                                   &mTexture, NULL);
 
-            SafeRelease(upper);
-            SafeRelease(lower);
+        if (FAILED(result))
+        {
+            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube storage texture, result: 0x%X.", result);
         }
     }
-}
 
-IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const
-{
-    return mTexture;
+    *outTexture = mTexture;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void TextureStorage9_Cube::initializeRenderTarget()
+gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage)
 {
-    if (mTexture != NULL && isRenderTarget())
-    {
-        IDirect3DSurface9 *surface = NULL;
+    ASSERT(destStorage);
+
+    TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(destStorage);
 
-        for (int i = 0; i < 6; ++i)
+    int levels = getLevelCount();
+    for (int f = 0; f < CUBE_FACE_COUNT; f++)
+    {
+        for (int i = 0; i < levels; i++)
         {
-            ASSERT(mRenderTarget[i] == NULL);
+            IDirect3DSurface9 *srcSurf = NULL;
+            gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf);
+            if (error.isError())
+            {
+                return error;
+            }
 
-            surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false);
+            IDirect3DSurface9 *dstSurf = NULL;
+            error = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf);
+            if (error.isError())
+            {
+                SafeRelease(srcSurf);
+                return error;
+            }
+
+            error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged());
 
-            mRenderTarget[i] = new RenderTarget9(mRenderer, surface);
+            SafeRelease(srcSurf);
+            SafeRelease(dstSurf);
+
+            if (error.isError())
+            {
+                return error;
+            }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-}
\ No newline at end of file
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h
index e698c7dd564..da0e1f2f18b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h
@@ -33,20 +33,28 @@ class TextureStorage9 : public TextureStorage
     D3DPOOL getPool() const;
     DWORD getUsage() const;
 
-    virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0;
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0;
-    virtual void generateMipmaps() = 0;
+    virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) = 0;
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0;
 
     virtual int getTopLevel() const;
     virtual bool isRenderTarget() const;
     virtual bool isManaged() const;
     virtual int getLevelCount() const;
 
+    virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type,
+                              const gl::PixelUnpackState &unpack, const uint8_t *pixelData);
+
   protected:
     int mTopLevel;
+    size_t mMipLevels;
+    size_t mTextureWidth;
+    size_t mTextureHeight;
+    GLenum mInternalFormat;
+    D3DFORMAT mTextureFormat;
+
     Renderer9 *mRenderer;
 
-    TextureStorage9(Renderer *renderer, DWORD usage);
+    TextureStorage9(Renderer9 *renderer, DWORD usage);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureStorage9);
@@ -58,22 +66,21 @@ class TextureStorage9 : public TextureStorage
 class TextureStorage9_2D : public TextureStorage9
 {
   public:
-    TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain);
-    TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
+    TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain);
+    TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
     virtual ~TextureStorage9_2D();
 
     static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage);
 
-    IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty);
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
-    virtual IDirect3DBaseTexture9 *getBaseTexture() const;
-    virtual void generateMipmaps();
+    gl::Error getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface);
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
+    virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture);
+    virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
+    virtual gl::Error copyToStorage(TextureStorage *destStorage);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D);
 
-    void initializeRenderTarget();
-
     IDirect3DTexture9 *mTexture;
     RenderTarget9 *mRenderTarget;
 };
@@ -81,23 +88,24 @@ class TextureStorage9_2D : public TextureStorage9
 class TextureStorage9_Cube : public TextureStorage9
 {
   public:
-    TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels);
+    TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels);
     virtual ~TextureStorage9_Cube();
 
     static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage);
 
-    IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty);
-    virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index);
-    virtual IDirect3DBaseTexture9 *getBaseTexture() const;
-    virtual void generateMipmaps();
+    gl::Error getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface);
+    virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
+    virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture);
+    virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
+    virtual gl::Error copyToStorage(TextureStorage *destStorage);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube);
 
-    void initializeRenderTarget();
+    static const size_t CUBE_FACE_COUNT = 6;
 
     IDirect3DCubeTexture9 *mTexture;
-    RenderTarget9 *mRenderTarget[6];
+    RenderTarget9 *mRenderTarget[CUBE_FACE_COUNT];
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h
index 66a6c64d81c..791c108462b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h
@@ -19,7 +19,7 @@ class Renderer9;
 class VertexArray9 : public VertexArrayImpl
 {
   public:
-    VertexArray9(rx::Renderer9 *renderer)
+    VertexArray9(Renderer9 *renderer)
         : VertexArrayImpl(),
           mRenderer(renderer)
     {
@@ -35,7 +35,7 @@ class VertexArray9 : public VertexArrayImpl
   private:
     DISALLOW_COPY_AND_ASSIGN(VertexArray9);
 
-    rx::Renderer9 *mRenderer;
+    Renderer9 *mRenderer;
 };
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp
index 4cf77791185..b90133097c9 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp
@@ -10,14 +10,14 @@
 #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
 #include "libGLESv2/renderer/vertexconversion.h"
-#include "libGLESv2/renderer/BufferImpl.h"
+#include "libGLESv2/renderer/d3d/BufferD3D.h"
 #include "libGLESv2/VertexAttribute.h"
 #include "libGLESv2/Buffer.h"
 
 namespace rx
 {
 
-VertexBuffer9::VertexBuffer9(rx::Renderer9 *renderer) : mRenderer(renderer)
+VertexBuffer9::VertexBuffer9(Renderer9 *renderer) : mRenderer(renderer)
 {
     mVertexBuffer = NULL;
     mBufferSize = 0;
@@ -97,8 +97,14 @@ gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib
     {
         if (buffer)
         {
-            BufferImpl *storage = buffer->getImplementation();
-            input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset);
+            BufferD3D *storage = BufferD3D::makeFromBuffer(buffer);
+            ASSERT(storage);
+            gl::Error error = storage->getData(&input);
+            if (error.isError())
+            {
+                return error;
+            }
+            input += static_cast<int>(attrib.offset);
         }
         else
         {
@@ -203,7 +209,7 @@ gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::s
         else
         {
             // Round up to divisor, if possible
-            elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
+            elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
         }
 
         if (d3d9VertexInfo.outputElementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h
index bdcf4bb64a3..9af2b98a6ed 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h
@@ -18,7 +18,7 @@ class Renderer9;
 class VertexBuffer9 : public VertexBuffer
 {
   public:
-    explicit VertexBuffer9(rx::Renderer9 *renderer);
+    explicit VertexBuffer9(Renderer9 *renderer);
     virtual ~VertexBuffer9();
 
     virtual gl::Error initialize(unsigned int size, bool dynamicUsage);
@@ -39,7 +39,7 @@ class VertexBuffer9 : public VertexBuffer
   private:
     DISALLOW_COPY_AND_ASSIGN(VertexBuffer9);
 
-    rx::Renderer9 *mRenderer;
+    Renderer9 *mRenderer;
 
     IDirect3DVertexBuffer9 *mVertexBuffer;
     unsigned int mBufferSize;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
index e7a91e62d69..a98b2081f3b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -9,6 +9,7 @@
 
 #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
+#include "libGLESv2/renderer/Workarounds.h"
 #include "libGLESv2/formatutils.h"
 #include "libGLESv2/Framebuffer.h"
 #include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
@@ -390,8 +391,9 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT
 
     caps->maxVertexUniformBlocks = 0;
 
-    const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 10;
-    const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 8;
+    // SM3 only supports 11 output variables, with a special 12th register for PSIZE.
+    const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 9;
+    const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 7;
     caps->maxVertexOutputComponents = ((deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) ? MAX_VERTEX_OUTPUT_VECTORS_SM3
                                                                                                : MAX_VERTEX_OUTPUT_VECTORS_SM2) * 4;
 
@@ -459,7 +461,7 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT
         extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
                                       !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
                                       !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
-                                      !(isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD);
+                                      !(!isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD);
     }
     else
     {
@@ -531,10 +533,24 @@ void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsize
     *levelOffset = upsampleCount;
 }
 
-RenderTarget9 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
+gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget9 **outRT)
 {
-    RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
-    return RenderTarget9::makeRenderTarget9(renderTarget);
+    RenderTarget *renderTarget = NULL;
+    gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget);
+    if (error.isError())
+    {
+        return error;
+    }
+    *outRT = RenderTarget9::makeRenderTarget9(renderTarget);
+    return gl::Error(GL_NO_ERROR);
+}
+
+Workarounds GenerateWorkarounds()
+{
+    Workarounds workarounds;
+    workarounds.mrtPerfWorkaround = true;
+    workarounds.setDataFasterThanImageUpload = false;
+    return workarounds;
 }
 
 }
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h
index b0a940e60ae..9760b9735a4 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h
@@ -12,6 +12,7 @@
 
 #include "libGLESv2/angletypes.h"
 #include "libGLESv2/Caps.h"
+#include "libGLESv2/Error.h"
 
 namespace gl
 {
@@ -21,6 +22,7 @@ class FramebufferAttachment;
 namespace rx
 {
 class RenderTarget9;
+struct Workarounds;
 
 namespace gl_d3d9
 {
@@ -74,7 +76,8 @@ inline bool isDeviceLostError(HRESULT errorCode)
     }
 }
 
-RenderTarget9 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment);
+gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget9 **outRT);
+Workarounds GenerateWorkarounds();
 
 }
 
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp
index f777b30be6f..159b4c7e9f5 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp
@@ -10,10 +10,6 @@
 
 #include "libGLESv2/renderer/loadimage.h"
 
-#if !defined(__SSE2__) && (defined(_M_X64) || _M_IX86_FP == 2)
-#define __SSE2__
-#endif
-
 namespace rx
 {
 
@@ -21,7 +17,12 @@ void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
                         const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
                         uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
 {
-#ifdef __SSE2__
+#if defined(_M_ARM)
+    // Ensure that this function is reported as not implemented for ARM builds because
+    // the instructions below are not present for that architecture.
+    UNIMPLEMENTED();
+    return;
+#else
     __m128i zeroWide = _mm_setzero_si128();
 
     for (size_t z = 0; z < depth; z++)
@@ -66,7 +67,12 @@ void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
                            const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
                            uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
 {
-#ifdef __SSE2__
+#if defined(_M_ARM)
+    // Ensure that this function is reported as not implemented for ARM builds because
+    // the instructions below are not present for that architecture.
+    UNIMPLEMENTED();
+    return;
+#else
     __m128i brMask = _mm_set1_epi32(0x00ff00ff);
 
     for (size_t z = 0; z < depth; z++)
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.cpp b/src/3rdparty/angle/src/libGLESv2/validationES.cpp
index f79bc97e4f6..265f4b4fba1 100644
--- a/src/3rdparty/angle/src/libGLESv2/validationES.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/validationES.cpp
@@ -24,6 +24,9 @@
 #include "common/mathutil.h"
 #include "common/utilities.h"
 
+// FIXME(jmadill): remove this when we support buffer data caching
+#include "libGLESv2/renderer/d3d/BufferD3D.h"
+
 namespace gl
 {
 
@@ -497,14 +500,26 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
 
     gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
     gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
-    if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
-        !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+
+    if (!readFramebuffer || !drawFramebuffer)
+    {
+        context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+        return false;
+    }
+
+    if (!readFramebuffer->completeness(context->getData()))
+    {
+        context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+        return false;
+    }
+
+    if (!drawFramebuffer->completeness(context->getData()))
     {
         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
         return false;
     }
 
-    if (drawFramebuffer->getSamples() != 0)
+    if (drawFramebuffer->getSamples(context->getData()) != 0)
     {
         context->recordError(Error(GL_INVALID_OPERATION));
         return false;
@@ -588,16 +603,20 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
                             return false;
                         }
 
-                        if (attachment->getActualFormat() != readColorBuffer->getActualFormat())
+                        // Return an error if the destination formats do not match
+                        if (attachment->getInternalFormat() != readColorBuffer->getInternalFormat())
                         {
                             context->recordError(Error(GL_INVALID_OPERATION));
                             return false;
                         }
                     }
                 }
-                if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
-                                                                        srcX0, srcY0, srcX1, srcY1,
-                                                                        dstX0, dstY0, dstX1, dstY1))
+
+                int readSamples = readFramebuffer->getSamples(context->getData());
+
+                if (readSamples != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
+                                                      srcX0, srcY0, srcX1, srcY1,
+                                                      dstX0, dstY0, dstX1, dstY1))
                 {
                     context->recordError(Error(GL_INVALID_OPERATION));
                     return false;
@@ -912,13 +931,14 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize
     gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
     ASSERT(framebuffer);
 
-    if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+    if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
     {
         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
         return false;
     }
 
-    if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0)
+    if (context->getState().getReadFramebuffer()->id() != 0 &&
+        framebuffer->getSamples(context->getData()) != 0)
     {
         context->recordError(Error(GL_INVALID_OPERATION));
         return false;
@@ -1172,7 +1192,7 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType,
         {
             Framebuffer *framebuffer = context->getState().getReadFramebuffer();
             ASSERT(framebuffer);
-            if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+            if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
             {
                 context->recordError(Error(GL_INVALID_OPERATION));
                 return false;
@@ -1236,13 +1256,13 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
     }
 
     gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
-    if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+    if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
     {
         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
         return false;
     }
 
-    if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0)
+    if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples(context->getData()) != 0)
     {
         context->recordError(Error(GL_INVALID_OPERATION));
         return false;
@@ -1441,7 +1461,7 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz
     }
 
     const gl::Framebuffer *fbo = state.getDrawFramebuffer();
-    if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE)
+    if (!fbo || fbo->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
     {
         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
         return false;
@@ -1667,11 +1687,20 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t
     // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
     if (elementArrayBuffer)
     {
-        GLint64 offset = reinterpret_cast<GLint64>(indices);
+        uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
         if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL))
         {
-            const void *dataPointer = elementArrayBuffer->getImplementation()->getData();
-            const uint8_t *offsetPointer = static_cast<const uint8_t *>(dataPointer) + offset;
+            // FIXME(jmadill): Use buffer data caching instead of the D3D back-end
+            rx::BufferD3D *bufferD3D = rx::BufferD3D::makeBufferD3D(elementArrayBuffer->getImplementation());
+            const uint8_t *dataPointer = NULL;
+            Error error = bufferD3D->getData(&dataPointer);
+            if (error.isError())
+            {
+                context->recordError(error);
+                return false;
+            }
+
+            const uint8_t *offsetPointer = dataPointer + offset;
             *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count);
         }
     }
@@ -1850,6 +1879,11 @@ bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
         return false;
     }
 
+    if (!ValidProgram(context, program))
+    {
+        return false;
+    }
+
     gl::Program *programObject = context->getProgram(program);
 
     if (!programObject || !programObject->isLinked())
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp b/src/3rdparty/angle/src/libGLESv2/validationES3.cpp
index 251c6ad2c4b..2d3a039e139 100644
--- a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/validationES3.cpp
@@ -542,7 +542,8 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
             return false;
         }
 
-        size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes;
+        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
+        size_t copyBytes = formatInfo.computeBlockSize(type, width, height);
         size_t offset = reinterpret_cast<size_t>(pixels);
 
         if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) ||
@@ -555,12 +556,15 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
 
         // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
         // indicated by type.
-        size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
-
-        if ((offset % dataBytesPerPixel) != 0)
+        if (!isCompressed)
         {
-            context->recordError(Error(GL_INVALID_OPERATION));
-            return false;
+            size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
+
+            if ((offset % dataBytesPerPixel) != 0)
+            {
+                context->recordError(Error(GL_INVALID_OPERATION));
+                return false;
+            }
         }
 
         // ...the buffer object's data store is currently mapped.
@@ -872,13 +876,14 @@ bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint le
 
     gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
 
-    if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+    if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
     {
         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
         return false;
     }
 
-    if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0)
+    if (context->getState().getReadFramebuffer()->id() != 0 &&
+        framebuffer->getSamples(context->getData()) != 0)
     {
         context->recordError(Error(GL_INVALID_OPERATION));
         return false;
@@ -1258,7 +1263,7 @@ bool ValidateClearBuffer(Context *context)
     }
 
     const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
-    if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE)
+    if (!fbo || fbo->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
     {
         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
         return false;
diff --git a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp
index 19a9644d709..97dfcaac513 100644
--- a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp
+++ b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp
@@ -24,6 +24,7 @@
  */
 
 #include <windows.h>
+#include "common/platform.h"
 
 #if _WIN32_WINNT_WINBLUE
 #include <versionhelpers.h>
@@ -52,7 +53,11 @@ bool isWindowsVistaOrGreater()
 
     if (!initialized) {
         initialized = true;
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+        cachedIsWindowsVistaOrGreater = true;
+#else
         cachedIsWindowsVistaOrGreater = IsWindowsVistaOrGreater();
+#endif
     }
     return cachedIsWindowsVistaOrGreater;
 }
diff --git a/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch b/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch
index d5e3697c4f7..ad3187ec7c0 100644
--- a/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch
+++ b/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch
@@ -1,178 +1,49 @@
-From f409f6837ce80d722eb6d2ff178b61b713d3e8c7 Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@digia.com>
-Date: Thu, 25 Sep 2014 13:23:19 +0300
+From bd27c33a4a7c48bd14b9b6c18c8cdce1c3aae155 Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@theqtcompany.com>
+Date: Fri, 14 Nov 2014 10:53:40 +0200
 Subject: [PATCH] General fixes for ANGLE 2.1
 
 - Fix commit.h include (use hard-coded version)
-- Fix undefined intptr_t in egl.h and eglext.h
 - Fix export mismatch in libEGL.cpp and libGLESv2.cpp
-- Remove D3D9 d3dcompiler.h include requirement in the translator
 - Normalize all precompiled shader names and includes
 - Remove third-party event tracing; it was hardly used in ANGLE
   and not enabled in Qt builds anyway.
 
 Change-Id: I22254aed62e89a26756ca0784bae95909189c0f9
 ---
- src/3rdparty/angle/include/EGL/egl.h               |   2 +-
- src/3rdparty/angle/include/EGL/eglext.h            |   2 +-
- src/3rdparty/angle/src/common/event_tracer.cpp     |  49 --
- src/3rdparty/angle/src/common/event_tracer.h       |  43 --
- src/3rdparty/angle/src/common/version.h            |   2 +-
- src/3rdparty/angle/src/libEGL/libEGL.cpp           |   3 +
- src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp     |   5 +
- src/3rdparty/angle/src/libGLESv2/libGLESv2.def     |   3 -
- .../angle/src/libGLESv2/libGLESv2_mingw32.def      |   3 -
- src/3rdparty/angle/src/libGLESv2/libGLESv2d.def    |   3 -
- .../angle/src/libGLESv2/libGLESv2d_mingw32.def     |   3 -
- .../angle/src/libGLESv2/renderer/Renderer.cpp      |   1 -
- .../angle/src/libGLESv2/renderer/SwapChain.h       |   4 -
- .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp    |   6 +-
- .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp    |  66 +-
- .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp   |  12 +-
- .../renderer/d3d/d3d11/PixelTransfer11.cpp         |  10 +-
- .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp   |   4 +-
- .../renderer/d3d/d3d11/shaders/Clear11.hlsl        |   4 +
- .../src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp      |  20 +-
- .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp  |  12 -
- .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps    |   6 +-
- .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs    |   4 +-
- .../src/third_party/trace_event/trace_event.h      | 826 ---------------------
- src/angle/src/common/common.pri                    |   2 -
- 25 files changed, 80 insertions(+), 1015 deletions(-)
- delete mode 100644 src/3rdparty/angle/src/common/event_tracer.cpp
- delete mode 100644 src/3rdparty/angle/src/common/event_tracer.h
- delete mode 100644 src/3rdparty/angle/src/third_party/trace_event/trace_event.h
+ src/3rdparty/angle/src/commit.h                    |  6 +-
+ src/3rdparty/angle/src/common/version.h            |  2 +-
+ .../src/common/winrt/CoreWindowNativeWindow.cpp    |  2 +-
+ src/3rdparty/angle/src/libEGL/libEGL.cpp           |  3 +
+ src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp     |  4 ++
+ src/3rdparty/angle/src/libGLESv2/libGLESv2.def     |  3 -
+ .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp    |  3 -
+ .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp    | 66 +++++++++++-----------
+ .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp   | 12 ++--
+ .../renderer/d3d/d3d11/PixelTransfer11.cpp         | 10 ++--
+ .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp   |  4 +-
+ .../renderer/d3d/d3d11/shaders/Clear11.hlsl        |  4 ++
+ .../src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp      | 20 +++----
+ .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp  | 12 ----
+ .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps    |  6 +-
+ .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs    |  4 +-
+ 16 files changed, 76 insertions(+), 85 deletions(-)
 
-diff --git a/src/3rdparty/angle/include/EGL/egl.h b/src/3rdparty/angle/include/EGL/egl.h
-index 12590a0..ab2f0cd 100644
---- a/src/3rdparty/angle/include/EGL/egl.h
-+++ b/src/3rdparty/angle/include/EGL/egl.h
-@@ -238,7 +238,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
- #ifndef EGL_VERSION_1_5
- #define EGL_VERSION_1_5 1
- typedef void *EGLSync;
--typedef intptr_t EGLAttrib;
-+typedef khronos_intptr_t EGLAttrib;
- typedef khronos_utime_nanoseconds_t EGLTime;
- #define EGL_CONTEXT_MAJOR_VERSION         0x3098
- #define EGL_CONTEXT_MINOR_VERSION         0x30FB
-diff --git a/src/3rdparty/angle/include/EGL/eglext.h b/src/3rdparty/angle/include/EGL/eglext.h
-index 9e29605..989359b 100644
---- a/src/3rdparty/angle/include/EGL/eglext.h
-+++ b/src/3rdparty/angle/include/EGL/eglext.h
-@@ -59,7 +59,7 @@ extern "C" {
- #ifndef EGL_KHR_cl_event2
- #define EGL_KHR_cl_event2 1
- typedef void *EGLSyncKHR;
--typedef intptr_t EGLAttribKHR;
-+typedef khronos_intptr_t EGLAttribKHR;
- typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
- #ifdef EGL_EGLEXT_PROTOTYPES
- EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
-diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp
-deleted file mode 100644
-index 353c69d..0000000
---- a/src/3rdparty/angle/src/common/event_tracer.cpp
-+++ /dev/null
-@@ -1,49 +0,0 @@
--// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
--// Use of this source code is governed by a BSD-style license that can be
--// found in the LICENSE file.
--
--#include "common/event_tracer.h"
--
--namespace gl
--{
--
--GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag;
--AddTraceEventFunc g_addTraceEvent;
--
--}  // namespace gl
--
--extern "C" {
--
--void TRACE_ENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag,
--                                          AddTraceEventFunc addTraceEvent)
--{
--    gl::g_getCategoryEnabledFlag = getCategoryEnabledFlag;
--    gl::g_addTraceEvent = addTraceEvent;
--}
--
--}  // extern "C"
--
--namespace gl
--{
--
--const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name)
--{
--    if (g_getCategoryEnabledFlag)
--    {
--        return g_getCategoryEnabledFlag(name);
--    }
--    static unsigned char disabled = 0;
--    return &disabled;
--}
--
--void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
--                        int numArgs, const char** argNames, const unsigned char* argTypes,
--                        const unsigned long long* argValues, unsigned char flags)
--{
--    if (g_addTraceEvent)
--    {
--        g_addTraceEvent(phase, categoryGroupEnabled, name, id, numArgs, argNames, argTypes, argValues, flags);
--    }
--}
--
--}  // namespace gl
-diff --git a/src/3rdparty/angle/src/common/event_tracer.h b/src/3rdparty/angle/src/common/event_tracer.h
-deleted file mode 100644
-index fa97435..0000000
---- a/src/3rdparty/angle/src/common/event_tracer.h
-+++ /dev/null
-@@ -1,43 +0,0 @@
--// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
--// Use of this source code is governed by a BSD-style license that can be
--// found in the LICENSE file.
--
--#ifndef COMMON_EVENT_TRACER_H_
--#define COMMON_EVENT_TRACER_H_
--
--#include "common/platform.h"
--
--#if !defined(TRACE_ENTRY)
--#   ifdef ANGLE_PLATFORM_WINDOWS
--#       define TRACE_ENTRY __stdcall
--#   else
--#       define TRACE_ENTRY
--#   endif // ANGLE_PLATFORM_WINDOWS
--#endif //TRACE_ENTRY
--
--extern "C" {
--
--typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name);
--typedef void (*AddTraceEventFunc)(char phase, const unsigned char* categoryGroupEnabled, const char* name,
--                                  unsigned long long id, int numArgs, const char** argNames,
--                                  const unsigned char* argTypes, const unsigned long long* argValues,
--                                  unsigned char flags);
--
--// extern "C" so that it has a reasonable name for GetProcAddress.
--void TRACE_ENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc get_category_enabled_flag,
--                                          AddTraceEventFunc add_trace_event_func);
--
--}
--
--namespace gl
--{
--
--const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name);
--
--void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
--                        int numArgs, const char** argNames, const unsigned char* argTypes,
--                        const unsigned long long* argValues, unsigned char flags);
--
--}
--
--#endif  // COMMON_EVENT_TRACER_H_
+diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h
+index 4c89a65..08fc893 100644
+--- a/src/3rdparty/angle/src/commit.h
++++ b/src/3rdparty/angle/src/commit.h
+@@ -7,8 +7,6 @@
+ //   This is a default commit hash header, when git is not available.
+ //
+ 
+-#define ANGLE_COMMIT_HASH "unknown hash"
++#define ANGLE_COMMIT_HASH "30d6c255d238"
+ #define ANGLE_COMMIT_HASH_SIZE 12
+-#define ANGLE_COMMIT_DATE "unknown date"
+-
+-#define ANGLE_DISABLE_PROGRAM_BINARY_LOAD
++#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000"
 diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h
 index d9148d1..f01e024 100644
 --- a/src/3rdparty/angle/src/common/version.h
@@ -183,8 +54,19 @@ index d9148d1..f01e024 100644
  
  #define ANGLE_MAJOR_VERSION 2
  #define ANGLE_MINOR_VERSION 1
+diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
+index 0de16f4..0e63fa5 100644
+--- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
++++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
+@@ -184,4 +184,4 @@ long ConvertDipsToPixels(float dips)
+     static const float dipsPerInch = 96.0f;
+     return lround((dips * GetLogicalDpi() / dipsPerInch));
+ }
+-}
+\ No newline at end of file
++}
 diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp
-index f9a4780..7ce2b93 100644
+index 851b723..6110698 100644
 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp
 +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp
 @@ -6,6 +6,9 @@
@@ -198,7 +80,7 @@ index f9a4780..7ce2b93 100644
  
  #include "common/debug.h"
 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
-index 198c0ee..07f5d47 100644
+index 2306168..587950a 100644
 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
 @@ -6,6 +6,10 @@
@@ -212,14 +94,6 @@ index 198c0ee..07f5d47 100644
  #include "common/version.h"
  #include "common/utilities.h"
  
-@@ -30,6 +34,7 @@
- #include "libGLESv2/validationES3.h"
- #include "libGLESv2/queryconversions.h"
- 
-+
- extern "C"
- {
- 
 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
 index 88dceb3..33557eb 100644
 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
@@ -231,93 +105,29 @@ index 88dceb3..33557eb 100644
 -
 -    ; Setting up TRACE macro callbacks
 -    SetTraceFunctionPointers        @284
-diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
-index d6272c4d..18ffcf6 100644
---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
-+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
-@@ -294,6 +294,3 @@ EXPORTS
-     glBindTexImage@4                         @158 NONAME
-     glCreateRenderer                         @177 NONAME
-     glDestroyRenderer                        @178 NONAME
--
--    ; Setting up TRACE macro callbacks
--    SetTraceFunctionPointers@8               @284
-diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
-index d301aa0..120371e 100644
---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
-+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
-@@ -294,6 +294,3 @@ EXPORTS
-     glBindTexImage                  @158 NONAME
-     glCreateRenderer                @177 NONAME
-     glDestroyRenderer               @178 NONAME
--
--    ; Setting up TRACE macro callbacks
--    SetTraceFunctionPointers        @284
-diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
-index a82d629..8c1306a 100644
---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
-+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
-@@ -294,6 +294,3 @@ EXPORTS
-     glBindTexImage@4                         @158 NONAME
-     glCreateRenderer                         @177 NONAME
-     glDestroyRenderer                        @178 NONAME
--
--    ; Setting up TRACE macro callbacks
--    SetTraceFunctionPointers@8               @284
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
-index df43012..910d028 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
-@@ -10,7 +10,6 @@
- #include "libGLESv2/Program.h"
- #include "libGLESv2/renderer/Renderer.h"
- #include "common/utilities.h"
--#include "third_party/trace_event/trace_event.h"
- #include "libGLESv2/Shader.h"
- 
- #if defined (ANGLE_ENABLE_D3D9)
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
-index c53b2af..12be9b3 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
-@@ -16,10 +16,6 @@
- #include <GLES2/gl2.h>
- #include <EGL/egl.h>
- 
--#if !defined(ANGLE_FORCE_VSYNC_OFF)
--#define ANGLE_FORCE_VSYNC_OFF 0
--#endif
--
- namespace rx
- {
- 
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-index df2e46c..acbd852 100644
+index 5c44fe0..bfeaf51 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-@@ -10,8 +10,6 @@
- 
+@@ -11,8 +11,6 @@
+ #include "common/features.h"
  #include "common/utilities.h"
  
 -#include "third_party/trace_event/trace_event.h"
 -
- namespace rx
+ // Definitions local to the translation unit
+ namespace
  {
- 
-@@ -28,7 +26,11 @@ HLSLCompiler::~HLSLCompiler()
+@@ -120,7 +118,6 @@ HLSLCompiler::~HLSLCompiler()
  
  bool HLSLCompiler::initialize()
  {
-+<<<<<<< HEAD
-     TRACE_EVENT0("gpu", "initializeCompiler");
-+=======
-+#if !defined(ANGLE_PLATFORM_WINRT)
-+>>>>>>> 429814a... ANGLE: remove event tracing
+-    TRACE_EVENT0("gpu", "initializeCompiler");
+ #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
  #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
      // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
-     static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
-index 3bdb9e7..72820a4 100644
+index 8ed1650..91e7552 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
 @@ -13,39 +13,39 @@
@@ -394,7 +204,7 @@ index 3bdb9e7..72820a4 100644
  #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h"
  #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
-index c60b7a6..5caa427 100644
+index 12905d0..4630762 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
 @@ -15,14 +15,14 @@
@@ -419,7 +229,7 @@ index c60b7a6..5caa427 100644
  namespace rx
  {
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
-index f54bacc..edaafec 100644
+index 1bc2bd8..a4072d8 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
 @@ -22,11 +22,11 @@
@@ -440,7 +250,7 @@ index f54bacc..edaafec 100644
  namespace rx
  {
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
-index 5ec132e..50dae4e 100644
+index 3fcacf6..834b7bd 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
 @@ -12,8 +12,8 @@
@@ -452,8 +262,8 @@ index 5ec132e..50dae4e 100644
 +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h"
 +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h"
  
- namespace rx
- {
+ #include "common/features.h"
+ #include "common/NativeWindow.h"
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl
 index 6deef2b..b4cf380 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl
@@ -485,7 +295,7 @@ index 6deef2b..b4cf380 100644
  }
  
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp
-index 80503d5..f061a32 100644
+index d4fcd17..2ca7a9c 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp
 @@ -27,20 +27,20 @@ namespace
@@ -520,11 +330,11 @@ index 80503d5..f061a32 100644
  }
  
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-index 73c1abc..e8564bd 100644
+index 3bac4ba..82963ec 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-@@ -39,8 +39,6 @@
- 
+@@ -42,8 +42,6 @@
+ #include "common/features.h"
  #include "common/utilities.h"
  
 -#include "third_party/trace_event/trace_event.h"
@@ -532,7 +342,7 @@ index 73c1abc..e8564bd 100644
  #include <sstream>
  
  // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
-@@ -190,7 +188,6 @@ EGLint Renderer9::initialize()
+@@ -185,7 +183,6 @@ EGLint Renderer9::initialize()
          return EGL_NOT_INITIALIZED;
      }
  
@@ -540,9 +350,9 @@ index 73c1abc..e8564bd 100644
      mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
  
      if (mD3d9Module == NULL)
-@@ -207,14 +204,12 @@ EGLint Renderer9::initialize()
+@@ -202,14 +199,12 @@ EGLint Renderer9::initialize()
      // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
-     if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
+     if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
      {
 -        TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface");
          ASSERT(mD3d9Ex);
@@ -555,7 +365,7 @@ index 73c1abc..e8564bd 100644
          mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
      }
  
-@@ -233,7 +228,6 @@ EGLint Renderer9::initialize()
+@@ -228,7 +223,6 @@ EGLint Renderer9::initialize()
  
      // Give up on getting device caps after about one second.
      {
@@ -563,7 +373,7 @@ index 73c1abc..e8564bd 100644
          for (int i = 0; i < 10; ++i)
          {
              result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
-@@ -268,7 +262,6 @@ EGLint Renderer9::initialize()
+@@ -263,7 +257,6 @@ EGLint Renderer9::initialize()
      }
  
      {
@@ -571,7 +381,7 @@ index 73c1abc..e8564bd 100644
          mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
      }
  
-@@ -305,7 +298,6 @@ EGLint Renderer9::initialize()
+@@ -300,7 +293,6 @@ EGLint Renderer9::initialize()
      static const TCHAR className[] = TEXT("STATIC");
  
      {
@@ -579,7 +389,7 @@ index 73c1abc..e8564bd 100644
          mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
      }
  
-@@ -313,7 +305,6 @@ EGLint Renderer9::initialize()
+@@ -308,7 +300,6 @@ EGLint Renderer9::initialize()
      DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
  
      {
@@ -587,7 +397,7 @@ index 73c1abc..e8564bd 100644
          result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
      }
      if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
-@@ -323,7 +314,6 @@ EGLint Renderer9::initialize()
+@@ -318,7 +309,6 @@ EGLint Renderer9::initialize()
  
      if (FAILED(result))
      {
@@ -595,7 +405,7 @@ index 73c1abc..e8564bd 100644
          result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
  
          if (FAILED(result))
-@@ -335,13 +325,11 @@ EGLint Renderer9::initialize()
+@@ -330,13 +320,11 @@ EGLint Renderer9::initialize()
  
      if (mD3d9Ex)
      {
@@ -662,858 +472,6 @@ index 3a36980..3bd611b 100644
  {
      VS_OUTPUT Out;
  
-diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h
-deleted file mode 100644
-index 1880056..0000000
---- a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h
-+++ /dev/null
-@@ -1,826 +0,0 @@
--// Copyright (c) 2013 The Chromium Authors. All rights reserved.
--// Use of this source code is governed by a BSD-style license that can be
--// found in the LICENSE file.
--
--// Trace events are for tracking application performance and resource usage.
--// Macros are provided to track:
--//    Begin and end of function calls
--//    Counters
--//
--// Events are issued against categories. Whereas LOG's
--// categories are statically defined, TRACE categories are created
--// implicitly with a string. For example:
--//   TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
--//
--// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
--//   TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
--//   doSomethingCostly()
--//   TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
--// Note: our tools can't always determine the correct BEGIN/END pairs unless
--// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you need them
--// to be in separate scopes.
--//
--// A common use case is to trace entire function scopes. This
--// issues a trace BEGIN and END automatically:
--//   void doSomethingCostly() {
--//     TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
--//     ...
--//   }
--//
--// Additional parameters can be associated with an event:
--//   void doSomethingCostly2(int howMuch) {
--//     TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
--//         "howMuch", howMuch);
--//     ...
--//   }
--//
--// The trace system will automatically add to this information the
--// current process id, thread id, and a timestamp in microseconds.
--//
--// To trace an asynchronous procedure such as an IPC send/receive, use ASYNC_BEGIN and
--// ASYNC_END:
--//   [single threaded sender code]
--//     static int send_count = 0;
--//     ++send_count;
--//     TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
--//     Send(new MyMessage(send_count));
--//   [receive code]
--//     void OnMyMessage(send_count) {
--//       TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
--//     }
--// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
--// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. Pointers can
--// be used for the ID parameter, and they will be mangled internally so that
--// the same pointer on two different processes will not match. For example:
--//   class MyTracedClass {
--//    public:
--//     MyTracedClass() {
--//       TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
--//     }
--//     ~MyTracedClass() {
--//       TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
--//     }
--//   }
--//
--// Trace event also supports counters, which is a way to track a quantity
--// as it varies over time. Counters are created with the following macro:
--//   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
--//
--// Counters are process-specific. The macro itself can be issued from any
--// thread, however.
--//
--// Sometimes, you want to track two counters at once. You can do this with two
--// counter macros:
--//   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
--//   TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
--// Or you can do it with a combined macro:
--//   TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
--//       "bytesPinned", g_myCounterValue[0],
--//       "bytesAllocated", g_myCounterValue[1]);
--// This indicates to the tracing UI that these counters should be displayed
--// in a single graph, as a summed area chart.
--//
--// Since counters are in a global namespace, you may want to disembiguate with a
--// unique ID, by using the TRACE_COUNTER_ID* variations.
--//
--// By default, trace collection is compiled in, but turned off at runtime.
--// Collecting trace data is the responsibility of the embedding
--// application. In Chrome's case, navigating to about:tracing will turn on
--// tracing and display data collected across all active processes.
--//
--//
--// Memory scoping note:
--// Tracing copies the pointers, not the string content, of the strings passed
--// in for category, name, and arg_names. Thus, the following code will
--// cause problems:
--//     char* str = strdup("impprtantName");
--//     TRACE_EVENT_INSTANT0("SUBSYSTEM", str);  // BAD!
--//     free(str);                   // Trace system now has dangling pointer
--//
--// To avoid this issue with the |name| and |arg_name| parameters, use the
--// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead.
--// Notes: The category must always be in a long-lived char* (i.e. static const).
--//        The |arg_values|, when used, are always deep copied with the _COPY
--//        macros.
--//
--// When are string argument values copied:
--// const char* arg_values are only referenced by default:
--//     TRACE_EVENT1("category", "name",
--//                  "arg1", "literal string is only referenced");
--// Use TRACE_STR_COPY to force copying of a const char*:
--//     TRACE_EVENT1("category", "name",
--//                  "arg1", TRACE_STR_COPY("string will be copied"));
--// std::string arg_values are always copied:
--//     TRACE_EVENT1("category", "name",
--//                  "arg1", std::string("string will be copied"));
--//
--//
--// Thread Safety:
--// A thread safe singleton and mutex are used for thread safety. Category
--// enabled flags are used to limit the performance impact when the system
--// is not enabled.
--//
--// TRACE_EVENT macros first cache a pointer to a category. The categories are
--// statically allocated and safe at all times, even after exit. Fetching a
--// category is protected by the TraceLog::lock_. Multiple threads initializing
--// the static variable is safe, as they will be serialized by the lock and
--// multiple calls will return the same pointer to the category.
--//
--// Then the category_enabled flag is checked. This is a unsigned char, and
--// not intended to be multithread safe. It optimizes access to addTraceEvent
--// which is threadsafe internally via TraceLog::lock_. The enabled flag may
--// cause some threads to incorrectly call or skip calling addTraceEvent near
--// the time of the system being enabled or disabled. This is acceptable as
--// we tolerate some data loss while the system is being enabled/disabled and
--// because addTraceEvent is threadsafe internally and checks the enabled state
--// again under lock.
--//
--// Without the use of these static category pointers and enabled flags all
--// trace points would carry a significant performance cost of aquiring a lock
--// and resolving the category.
--
--#ifndef COMMON_TRACE_EVENT_H_
--#define COMMON_TRACE_EVENT_H_
--
--#include <string>
--
--#include "common/event_tracer.h"
--
--// By default, const char* argument values are assumed to have long-lived scope
--// and will not be copied. Use this macro to force a const char* to be copied.
--#define TRACE_STR_COPY(str) \
--    WebCore::TraceEvent::TraceStringWithCopy(str)
--
--// Records a pair of begin and end events called "name" for the current
--// scope, with 0, 1 or 2 associated arguments. If the category is not
--// enabled, then this does nothing.
--// - category and name strings must have application lifetime (statics or
--//   literals). They may not include " chars.
--#define TRACE_EVENT0(category, name) \
--    INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name)
--#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val)
--#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
--    INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val, \
--        arg2_name, arg2_val)
--
--// Records a single event called "name" immediately, with 0, 1 or 2
--// associated arguments. If the category is not enabled, then this
--// does nothing.
--// - category and name strings must have application lifetime (statics or
--//   literals). They may not include " chars.
--#define TRACE_EVENT_INSTANT0(category, name) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
--        category, name, TRACE_EVENT_FLAG_NONE)
--#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
--        category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
--#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
--        arg2_name, arg2_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
--        category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
--        arg2_name, arg2_val)
--#define TRACE_EVENT_COPY_INSTANT0(category, name) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
--        category, name, TRACE_EVENT_FLAG_COPY)
--#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
--        category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
--#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \
--        arg2_name, arg2_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
--        category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
--        arg2_name, arg2_val)
--
--// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
--// associated arguments. If the category is not enabled, then this
--// does nothing.
--// - category and name strings must have application lifetime (statics or
--//   literals). They may not include " chars.
--#define TRACE_EVENT_BEGIN0(category, name) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
--        category, name, TRACE_EVENT_FLAG_NONE)
--#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
--        category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
--#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \
--        arg2_name, arg2_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
--        category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
--        arg2_name, arg2_val)
--#define TRACE_EVENT_COPY_BEGIN0(category, name) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
--        category, name, TRACE_EVENT_FLAG_COPY)
--#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
--        category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
--#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \
--        arg2_name, arg2_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
--        category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
--        arg2_name, arg2_val)
--
--// Records a single END event for "name" immediately. If the category
--// is not enabled, then this does nothing.
--// - category and name strings must have application lifetime (statics or
--//   literals). They may not include " chars.
--#define TRACE_EVENT_END0(category, name) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
--        category, name, TRACE_EVENT_FLAG_NONE)
--#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
--        category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
--#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \
--        arg2_name, arg2_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
--        category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
--        arg2_name, arg2_val)
--#define TRACE_EVENT_COPY_END0(category, name) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
--        category, name, TRACE_EVENT_FLAG_COPY)
--#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
--        category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
--#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \
--        arg2_name, arg2_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
--        category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
--        arg2_name, arg2_val)
--
--// Records the value of a counter called "name" immediately. Value
--// must be representable as a 32 bit integer.
--// - category and name strings must have application lifetime (statics or
--//   literals). They may not include " chars.
--#define TRACE_COUNTER1(category, name, value) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
--        category, name, TRACE_EVENT_FLAG_NONE, \
--        "value", static_cast<int>(value))
--#define TRACE_COPY_COUNTER1(category, name, value) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
--        category, name, TRACE_EVENT_FLAG_COPY, \
--        "value", static_cast<int>(value))
--
--// Records the values of a multi-parted counter called "name" immediately.
--// The UI will treat value1 and value2 as parts of a whole, displaying their
--// values as a stacked-bar chart.
--// - category and name strings must have application lifetime (statics or
--//   literals). They may not include " chars.
--#define TRACE_COUNTER2(category, name, value1_name, value1_val, \
--        value2_name, value2_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
--        category, name, TRACE_EVENT_FLAG_NONE, \
--        value1_name, static_cast<int>(value1_val), \
--        value2_name, static_cast<int>(value2_val))
--#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \
--        value2_name, value2_val) \
--    INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
--        category, name, TRACE_EVENT_FLAG_COPY, \
--        value1_name, static_cast<int>(value1_val), \
--        value2_name, static_cast<int>(value2_val))
--
--// Records the value of a counter called "name" immediately. Value
--// must be representable as a 32 bit integer.
--// - category and name strings must have application lifetime (statics or
--//   literals). They may not include " chars.
--// - |id| is used to disambiguate counters with the same name. It must either
--//   be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
--//   will be xored with a hash of the process ID so that the same pointer on
--//   two different processes will not collide.
--#define TRACE_COUNTER_ID1(category, name, id, value) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
--        category, name, id, TRACE_EVENT_FLAG_NONE, \
--        "value", static_cast<int>(value))
--#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
--        category, name, id, TRACE_EVENT_FLAG_COPY, \
--        "value", static_cast<int>(value))
--
--// Records the values of a multi-parted counter called "name" immediately.
--// The UI will treat value1 and value2 as parts of a whole, displaying their
--// values as a stacked-bar chart.
--// - category and name strings must have application lifetime (statics or
--//   literals). They may not include " chars.
--// - |id| is used to disambiguate counters with the same name. It must either
--//   be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
--//   will be xored with a hash of the process ID so that the same pointer on
--//   two different processes will not collide.
--#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \
--        value2_name, value2_val) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
--        category, name, id, TRACE_EVENT_FLAG_NONE, \
--        value1_name, static_cast<int>(value1_val), \
--        value2_name, static_cast<int>(value2_val))
--#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \
--        value2_name, value2_val) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
--        category, name, id, TRACE_EVENT_FLAG_COPY, \
--        value1_name, static_cast<int>(value1_val), \
--        value2_name, static_cast<int>(value2_val))
--
--// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
--// associated arguments. If the category is not enabled, then this
--// does nothing.
--// - category and name strings must have application lifetime (statics or
--//   literals). They may not include " chars.
--// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC
--//   events are considered to match if their category, name and id values all
--//   match. |id| must either be a pointer or an integer value up to 64 bits. If
--//   it's a pointer, the bits will be xored with a hash of the process ID so
--//   that the same pointer on two different processes will not collide.
--// An asynchronous operation can consist of multiple phases. The first phase is
--// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
--// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.
--// An async operation can span threads and processes, but all events in that
--// operation must use the same |name| and |id|. Each event can have its own
--// args.
--#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
--        category, name, id, TRACE_EVENT_FLAG_NONE)
--#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
--        category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
--#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
--        arg2_name, arg2_val) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
--        category, name, id, TRACE_EVENT_FLAG_NONE, \
--        arg1_name, arg1_val, arg2_name, arg2_val)
--#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
--        category, name, id, TRACE_EVENT_FLAG_COPY)
--#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
--        category, name, id, TRACE_EVENT_FLAG_COPY, \
--        arg1_name, arg1_val)
--#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
--        arg2_name, arg2_val) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
--        category, name, id, TRACE_EVENT_FLAG_COPY, \
--        arg1_name, arg1_val, arg2_name, arg2_val)
--
--// Records a single ASYNC_STEP event for |step| immediately. If the category
--// is not enabled, then this does nothing. The |name| and |id| must match the
--// ASYNC_BEGIN event above. The |step| param identifies this step within the
--// async event. This should be called at the beginning of the next phase of an
--// asynchronous operation.
--#define TRACE_EVENT_ASYNC_STEP0(category, name, id, step) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
--        category, name, id, TRACE_EVENT_FLAG_NONE, "step", step)
--#define TRACE_EVENT_ASYNC_STEP1(category, name, id, step, \
--                                      arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
--        category, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
--        arg1_name, arg1_val)
--#define TRACE_EVENT_COPY_ASYNC_STEP0(category, name, id, step) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
--        category, name, id, TRACE_EVENT_FLAG_COPY, "step", step)
--#define TRACE_EVENT_COPY_ASYNC_STEP1(category, name, id, step, \
--        arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
--        category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \
--        arg1_name, arg1_val)
--
--// Records a single ASYNC_END event for "name" immediately. If the category
--// is not enabled, then this does nothing.
--#define TRACE_EVENT_ASYNC_END0(category, name, id) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
--        category, name, id, TRACE_EVENT_FLAG_NONE)
--#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
--        category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
--#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
--        arg2_name, arg2_val) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
--        category, name, id, TRACE_EVENT_FLAG_NONE, \
--        arg1_name, arg1_val, arg2_name, arg2_val)
--#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
--        category, name, id, TRACE_EVENT_FLAG_COPY)
--#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
--        category, name, id, TRACE_EVENT_FLAG_COPY, \
--        arg1_name, arg1_val)
--#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
--        arg2_name, arg2_val) \
--    INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
--        category, name, id, TRACE_EVENT_FLAG_COPY, \
--        arg1_name, arg1_val, arg2_name, arg2_val)
--
--// Creates a scope of a sampling state with the given category and name (both must
--// be constant strings). These states are intended for a sampling profiler.
--// Implementation note: we store category and name together because we don't
--// want the inconsistency/expense of storing two pointers.
--// |thread_bucket| is [0..2] and is used to statically isolate samples in one
--// thread from others.
--//
--// {  // The sampling state is set within this scope.
--//    TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name");
--//    ...;
--// }
--#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \
--    TraceEvent::SamplingStateScope<bucket_number> traceEventSamplingScope(category "\0" name);
--
--// Returns a current sampling state of the given bucket.
--// The format of the returned string is "category\0name".
--#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \
--    TraceEvent::SamplingStateScope<bucket_number>::current()
--
--// Sets a current sampling state of the given bucket.
--// |category| and |name| have to be constant strings.
--#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \
--    TraceEvent::SamplingStateScope<bucket_number>::set(category "\0" name)
--
--// Sets a current sampling state of the given bucket.
--// |categoryAndName| doesn't need to be a constant string.
--// The format of the string is "category\0name".
--#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, categoryAndName) \
--    TraceEvent::SamplingStateScope<bucket_number>::set(categoryAndName)
--
--// Syntactic sugars for the sampling tracing in the main thread.
--#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \
--    TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name)
--#define TRACE_EVENT_GET_SAMPLING_STATE() \
--    TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0)
--#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \
--    TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name)
--#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(categoryAndName) \
--    TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(0, categoryAndName)
--
--////////////////////////////////////////////////////////////////////////////////
--// Implementation specific tracing API definitions.
--
--// Get a pointer to the enabled state of the given trace category. Only
--// long-lived literal strings should be given as the category name. The returned
--// pointer can be held permanently in a local static for example. If the
--// unsigned char is non-zero, tracing is enabled. If tracing is enabled,
--// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
--// between the load of the tracing state and the call to
--// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
--// for best performance when tracing is disabled.
--// const unsigned char*
--//     TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name)
--#define TRACE_EVENT_API_GET_CATEGORY_ENABLED \
--    gl::TraceGetTraceCategoryEnabledFlag
--
--// Add a trace event to the platform tracing system.
--// void TRACE_EVENT_API_ADD_TRACE_EVENT(
--//                    char phase,
--//                    const unsigned char* category_enabled,
--//                    const char* name,
--//                    unsigned long long id,
--//                    int num_args,
--//                    const char** arg_names,
--//                    const unsigned char* arg_types,
--//                    const unsigned long long* arg_values,
--//                    unsigned char flags)
--#define TRACE_EVENT_API_ADD_TRACE_EVENT \
--    gl::TraceAddTraceEvent
--
--////////////////////////////////////////////////////////////////////////////////
--
--// Implementation detail: trace event macros create temporary variables
--// to keep instrumentation overhead low. These macros give each temporary
--// variable a unique name based on the line number to prevent name collissions.
--#define INTERNAL_TRACE_EVENT_UID3(a, b) \
--    trace_event_unique_##a##b
--#define INTERNAL_TRACE_EVENT_UID2(a, b) \
--    INTERNAL_TRACE_EVENT_UID3(a, b)
--#define INTERNALTRACEEVENTUID(name_prefix) \
--    INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
--
--// Implementation detail: internal macro to create static category.
--#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \
--    static const unsigned char* INTERNALTRACEEVENTUID(catstatic) = 0; \
--    if (!INTERNALTRACEEVENTUID(catstatic)) \
--      INTERNALTRACEEVENTUID(catstatic) = \
--          TRACE_EVENT_API_GET_CATEGORY_ENABLED(category);
--
--// Implementation detail: internal macro to create static category and add
--// event if the category is enabled.
--#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \
--    do { \
--        INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
--        if (*INTERNALTRACEEVENTUID(catstatic)) { \
--            gl::TraceEvent::addTraceEvent( \
--                phase, INTERNALTRACEEVENTUID(catstatic), name, \
--                gl::TraceEvent::noEventId, flags, ##__VA_ARGS__); \
--        } \
--    } while (0)
--
--// Implementation detail: internal macro to create static category and add begin
--// event if the category is enabled. Also adds the end event when the scope
--// ends.
--#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \
--    INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
--    gl::TraceEvent::TraceEndOnScopeClose \
--        INTERNALTRACEEVENTUID(profileScope); \
--    if (*INTERNALTRACEEVENTUID(catstatic)) { \
--      gl::TraceEvent::addTraceEvent( \
--          TRACE_EVENT_PHASE_BEGIN, \
--          INTERNALTRACEEVENTUID(catstatic), \
--          name, gl::TraceEvent::noEventId, \
--          TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
--      INTERNALTRACEEVENTUID(profileScope).initialize( \
--          INTERNALTRACEEVENTUID(catstatic), name); \
--    }
--
--// Implementation detail: internal macro to create static category and add
--// event if the category is enabled.
--#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \
--                                         ...) \
--    do { \
--        INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
--        if (*INTERNALTRACEEVENTUID(catstatic)) { \
--            unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \
--            gl::TraceEvent::TraceID traceEventTraceID( \
--                id, &traceEventFlags); \
--            gl::TraceEvent::addTraceEvent( \
--                phase, INTERNALTRACEEVENTUID(catstatic), \
--                name, traceEventTraceID.data(), traceEventFlags, \
--                ##__VA_ARGS__); \
--        } \
--    } while (0)
--
--// Notes regarding the following definitions:
--// New values can be added and propagated to third party libraries, but existing
--// definitions must never be changed, because third party libraries may use old
--// definitions.
--
--// Phase indicates the nature of an event entry. E.g. part of a begin/end pair.
--#define TRACE_EVENT_PHASE_BEGIN    ('B')
--#define TRACE_EVENT_PHASE_END      ('E')
--#define TRACE_EVENT_PHASE_INSTANT  ('I')
--#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S')
--#define TRACE_EVENT_PHASE_ASYNC_STEP  ('T')
--#define TRACE_EVENT_PHASE_ASYNC_END   ('F')
--#define TRACE_EVENT_PHASE_METADATA ('M')
--#define TRACE_EVENT_PHASE_COUNTER  ('C')
--#define TRACE_EVENT_PHASE_SAMPLE  ('P')
--
--// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
--#define TRACE_EVENT_FLAG_NONE        (static_cast<unsigned char>(0))
--#define TRACE_EVENT_FLAG_COPY        (static_cast<unsigned char>(1 << 0))
--#define TRACE_EVENT_FLAG_HAS_ID      (static_cast<unsigned char>(1 << 1))
--#define TRACE_EVENT_FLAG_MANGLE_ID   (static_cast<unsigned char>(1 << 2))
--
--// Type values for identifying types in the TraceValue union.
--#define TRACE_VALUE_TYPE_BOOL         (static_cast<unsigned char>(1))
--#define TRACE_VALUE_TYPE_UINT         (static_cast<unsigned char>(2))
--#define TRACE_VALUE_TYPE_INT          (static_cast<unsigned char>(3))
--#define TRACE_VALUE_TYPE_DOUBLE       (static_cast<unsigned char>(4))
--#define TRACE_VALUE_TYPE_POINTER      (static_cast<unsigned char>(5))
--#define TRACE_VALUE_TYPE_STRING       (static_cast<unsigned char>(6))
--#define TRACE_VALUE_TYPE_COPY_STRING  (static_cast<unsigned char>(7))
--
--
--namespace gl {
--
--namespace TraceEvent {
--
--// Specify these values when the corresponding argument of addTraceEvent is not
--// used.
--const int zeroNumArgs = 0;
--const unsigned long long noEventId = 0;
--
--// TraceID encapsulates an ID that can either be an integer or pointer. Pointers
--// are mangled with the Process ID so that they are unlikely to collide when the
--// same pointer is used on different processes.
--class TraceID {
--public:
--    explicit TraceID(const void* id, unsigned char* flags) :
--        m_data(static_cast<unsigned long long>(reinterpret_cast<unsigned long>(id)))
--    {
--        *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
--    }
--    explicit TraceID(unsigned long long id, unsigned char* flags) : m_data(id) { (void)flags; }
--    explicit TraceID(unsigned long id, unsigned char* flags) : m_data(id) { (void)flags; }
--    explicit TraceID(unsigned int id, unsigned char* flags) : m_data(id) { (void)flags; }
--    explicit TraceID(unsigned short id, unsigned char* flags) : m_data(id) { (void)flags; }
--    explicit TraceID(unsigned char id, unsigned char* flags) : m_data(id) { (void)flags; }
--    explicit TraceID(long long id, unsigned char* flags) :
--        m_data(static_cast<unsigned long long>(id)) { (void)flags; }
--    explicit TraceID(long id, unsigned char* flags) :
--        m_data(static_cast<unsigned long long>(id)) { (void)flags; }
--    explicit TraceID(int id, unsigned char* flags) :
--        m_data(static_cast<unsigned long long>(id)) { (void)flags; }
--    explicit TraceID(short id, unsigned char* flags) :
--        m_data(static_cast<unsigned long long>(id)) { (void)flags; }
--    explicit TraceID(signed char id, unsigned char* flags) :
--        m_data(static_cast<unsigned long long>(id)) { (void)flags; }
--
--    unsigned long long data() const { return m_data; }
--
--private:
--    unsigned long long m_data;
--};
--
--// Simple union to store various types as unsigned long long.
--union TraceValueUnion {
--    bool m_bool;
--    unsigned long long m_uint;
--    long long m_int;
--    double m_double;
--    const void* m_pointer;
--    const char* m_string;
--};
--
--// Simple container for const char* that should be copied instead of retained.
--class TraceStringWithCopy {
--public:
--    explicit TraceStringWithCopy(const char* str) : m_str(str) { }
--    operator const char* () const { return m_str; }
--private:
--    const char* m_str;
--};
--
--// Define setTraceValue for each allowed type. It stores the type and
--// value in the return arguments. This allows this API to avoid declaring any
--// structures so that it is portable to third_party libraries.
--#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \
--                                         union_member, \
--                                         value_type_id) \
--    static inline void setTraceValue(actual_type arg, \
--                                     unsigned char* type, \
--                                     unsigned long long* value) { \
--        TraceValueUnion typeValue; \
--        typeValue.union_member = arg; \
--        *type = value_type_id; \
--        *value = typeValue.m_uint; \
--    }
--// Simpler form for int types that can be safely casted.
--#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \
--                                             value_type_id) \
--    static inline void setTraceValue(actual_type arg, \
--                                     unsigned char* type, \
--                                     unsigned long long* value) { \
--        *type = value_type_id; \
--        *value = static_cast<unsigned long long>(arg); \
--    }
--
--INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT)
--INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
--INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)
--INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
--INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)
--INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
--INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)
--INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
--INTERNAL_DECLARE_SET_TRACE_VALUE(bool, m_bool, TRACE_VALUE_TYPE_BOOL)
--INTERNAL_DECLARE_SET_TRACE_VALUE(double, m_double, TRACE_VALUE_TYPE_DOUBLE)
--INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, m_pointer,
--                                 TRACE_VALUE_TYPE_POINTER)
--INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, m_string,
--                                 TRACE_VALUE_TYPE_STRING)
--INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, m_string,
--                                 TRACE_VALUE_TYPE_COPY_STRING)
--
--#undef INTERNAL_DECLARE_SET_TRACE_VALUE
--#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
--
--static inline void setTraceValue(const std::string& arg,
--                                 unsigned char* type,
--                                 unsigned long long* value) {
--    TraceValueUnion typeValue;
--    typeValue.m_string = arg.data();
--    *type = TRACE_VALUE_TYPE_COPY_STRING;
--    *value = typeValue.m_uint;
--}
--
--// These addTraceEvent template functions are defined here instead of in the
--// macro, because the arg values could be temporary string objects. In order to
--// store pointers to the internal c_str and pass through to the tracing API, the
--// arg values must live throughout these procedures.
--
--static inline void addTraceEvent(char phase,
--                                const unsigned char* categoryEnabled,
--                                const char* name,
--                                unsigned long long id,
--                                unsigned char flags) {
--    TRACE_EVENT_API_ADD_TRACE_EVENT(
--        phase, categoryEnabled, name, id,
--        zeroNumArgs, 0, 0, 0,
--        flags);
--}
--
--template<class ARG1_TYPE>
--static inline void addTraceEvent(char phase,
--                                const unsigned char* categoryEnabled,
--                                const char* name,
--                                unsigned long long id,
--                                unsigned char flags,
--                                const char* arg1Name,
--                                const ARG1_TYPE& arg1Val) {
--    const int numArgs = 1;
--    unsigned char argTypes[1];
--    unsigned long long argValues[1];
--    setTraceValue(arg1Val, &argTypes[0], &argValues[0]);
--    TRACE_EVENT_API_ADD_TRACE_EVENT(
--        phase, categoryEnabled, name, id,
--        numArgs, &arg1Name, argTypes, argValues,
--        flags);
--}
--
--template<class ARG1_TYPE, class ARG2_TYPE>
--static inline void addTraceEvent(char phase,
--                                const unsigned char* categoryEnabled,
--                                const char* name,
--                                unsigned long long id,
--                                unsigned char flags,
--                                const char* arg1Name,
--                                const ARG1_TYPE& arg1Val,
--                                const char* arg2Name,
--                                const ARG2_TYPE& arg2Val) {
--    const int numArgs = 2;
--    const char* argNames[2] = { arg1Name, arg2Name };
--    unsigned char argTypes[2];
--    unsigned long long argValues[2];
--    setTraceValue(arg1Val, &argTypes[0], &argValues[0]);
--    setTraceValue(arg2Val, &argTypes[1], &argValues[1]);
--    return TRACE_EVENT_API_ADD_TRACE_EVENT(
--        phase, categoryEnabled, name, id,
--        numArgs, argNames, argTypes, argValues,
--        flags);
--}
--
--// Used by TRACE_EVENTx macro. Do not use directly.
--class TraceEndOnScopeClose {
--public:
--    // Note: members of m_data intentionally left uninitialized. See initialize.
--    TraceEndOnScopeClose() : m_pdata(0) { }
--    ~TraceEndOnScopeClose()
--    {
--        if (m_pdata)
--            addEventIfEnabled();
--    }
--
--    void initialize(const unsigned char* categoryEnabled,
--                    const char* name)
--    {
--        m_data.categoryEnabled = categoryEnabled;
--        m_data.name = name;
--        m_pdata = &m_data;
--    }
--
--private:
--    // Add the end event if the category is still enabled.
--    void addEventIfEnabled()
--    {
--        // Only called when m_pdata is non-null.
--        if (*m_pdata->categoryEnabled) {
--            TRACE_EVENT_API_ADD_TRACE_EVENT(
--                TRACE_EVENT_PHASE_END,
--                m_pdata->categoryEnabled,
--                m_pdata->name, noEventId,
--                zeroNumArgs, 0, 0, 0,
--                TRACE_EVENT_FLAG_NONE);
--        }
--    }
--
--    // This Data struct workaround is to avoid initializing all the members
--    // in Data during construction of this object, since this object is always
--    // constructed, even when tracing is disabled. If the members of Data were
--    // members of this class instead, compiler warnings occur about potential
--    // uninitialized accesses.
--    struct Data {
--        const unsigned char* categoryEnabled;
--        const char* name;
--    };
--    Data* m_pdata;
--    Data m_data;
--};
--
--// TraceEventSamplingStateScope records the current sampling state
--// and sets a new sampling state. When the scope exists, it restores
--// the sampling state having recorded.
--template<size_t BucketNumber>
--class SamplingStateScope {
--public:
--    SamplingStateScope(const char* categoryAndName)
--    {
--        m_previousState = SamplingStateScope<BucketNumber>::current();
--        SamplingStateScope<BucketNumber>::set(categoryAndName);
--    }
--
--    ~SamplingStateScope()
--    {
--        SamplingStateScope<BucketNumber>::set(m_previousState);
--    }
--
--    // FIXME: Make load/store to traceSamplingState[] thread-safe and atomic.
--    static inline const char* current()
--    {
--        return reinterpret_cast<const char*>(*gl::traceSamplingState[BucketNumber]);
--    }
--    static inline void set(const char* categoryAndName)
--    {
--        *gl::traceSamplingState[BucketNumber] = reinterpret_cast<long>(const_cast<char*>(categoryAndName));
--    }
--
--private:
--    const char* m_previousState;
--};
--
--} // namespace TraceEvent
--
--} // namespace gl
--
--#endif
-diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri
-index fd1c31c..8baedc5 100644
---- a/src/angle/src/common/common.pri
-+++ b/src/angle/src/common/common.pri
-@@ -51,7 +51,6 @@ static: DEFINES *= QT_OPENGL_ES_2_ANGLE_STATIC
- HEADERS +=  \
-     $$ANGLE_DIR/src/common/angleutils.h \
-     $$ANGLE_DIR/src/common/debug.h \
--    $$ANGLE_DIR/src/common/event_tracer.h \
-     $$ANGLE_DIR/src/common/mathutil.h \
-     $$ANGLE_DIR/src/common/platform.h \
-     $$ANGLE_DIR/src/common/RefCountObject.h \
-@@ -61,7 +60,6 @@ HEADERS +=  \
- SOURCES +=  \
-     $$ANGLE_DIR/src/common/angleutils.cpp \
-     $$ANGLE_DIR/src/common/debug.cpp \
--    $$ANGLE_DIR/src/common/event_tracer.cpp \
-     $$ANGLE_DIR/src/common/RefCountObject.cpp \
-     $$ANGLE_DIR/src/common/tls.cpp
- 
 -- 
-1.9.0.msysgit.0
+1.9.4.msysgit.1
 
diff --git a/src/angle/patches/0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch b/src/angle/patches/0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch
deleted file mode 100644
index f2252540eb0..00000000000
--- a/src/angle/patches/0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 3ea314039783d2e6e558cb10aa86dbf278631eef Mon Sep 17 00:00:00 2001
-From: Thomas Hartmann <Thomas.Hartmann@digia.com>
-Date: Tue, 16 Sep 2014 23:24:24 +0300
-Subject: [PATCH 01/16] Fix compilation for MSVC 2008 and std::tuple
-
-For MSVC 2008 make_tuple is in the tr1 namespace.
-
-Change-Id: I4a51f6cabdf068993869b404b12ed1484a21a9d4
----
- src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp
-index d472e14..f68ac38 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp
-@@ -111,7 +111,11 @@ IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c)
- 
- bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const
- {
-+#if defined(_MSC_VER) && _MSC_VER < 1600
-+    return std::tr1::make_tuple(type, offset, count) < std::tr1::make_tuple(rhs.type, rhs.offset, rhs.count);
-+#else
-     return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count);
-+#endif
- }
- 
- IndexRangeCache::IndexBounds::IndexBounds()
--- 
-1.9.0.msysgit.0
-
diff --git a/src/angle/patches/0002-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch b/src/angle/patches/0002-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch
deleted file mode 100644
index 322d1211491..00000000000
--- a/src/angle/patches/0002-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 9f1217589c029d2f91e863c54f7f9d52ef496f71 Mon Sep 17 00:00:00 2001
-From: Kai Koehne <kai.koehne@digia.com>
-Date: Tue, 16 Sep 2014 23:33:42 +0300
-Subject: [PATCH 02/16] Fix compilation of ANGLE with mingw-tdm64 gcc 4.8.1
-
-Do not rely on sprintf_s being declared/defined. This also fixes
-deployment to Windows XP.
-
-See https://chromium-review.googlesource.com/#/c/182975/ for a similar
-commit proposed upstream.
-
-Task-number: QTBUG-36242
-Change-Id: I520e2f61aeab34963e7a57baafd413c7db93f110
----
- src/3rdparty/angle/src/libEGL/Display.cpp | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp
-index ecf3395..aaebdb3 100644
---- a/src/3rdparty/angle/src/libEGL/Display.cpp
-+++ b/src/3rdparty/angle/src/libEGL/Display.cpp
-@@ -597,7 +597,7 @@ void Display::initVendorString()
-     if (mRenderer && mRenderer->getLUID(&adapterLuid))
-     {
-         char adapterLuidString[64];
--        sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
-+        snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
- 
-         mVendorString += adapterLuidString;
-     }
--- 
-1.9.0.msysgit.0
-
diff --git a/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch b/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch
index 1dfe6154e7f..45a3f17ccab 100644
--- a/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch
+++ b/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch
@@ -1,6 +1,6 @@
-From cb00356bad800ca2397301cb8b79ad0b097bddd8 Mon Sep 17 00:00:00 2001
+From 3a39939b5eba9f788789961c4800ba62618f758c Mon Sep 17 00:00:00 2001
 From: Friedemann Kleint <Friedemann.Kleint@digia.com>
-Date: Tue, 16 Sep 2014 23:43:00 +0300
+Date: Tue, 11 Nov 2014 10:26:32 +0200
 Subject: [PATCH 04/16] Make it possible to link ANGLE statically for
  single-thread use.
 
@@ -11,8 +11,8 @@ Change-Id: Ifab25a820adf5953bb3b09036de53dbf7f1a7fd5
 ---
  src/3rdparty/angle/include/KHR/khrplatform.h |  2 +-
  src/3rdparty/angle/src/libEGL/main.cpp       | 10 ++++++++++
- src/3rdparty/angle/src/libGLESv2/main.cpp    | 10 ++++++++++
- 3 files changed, 21 insertions(+), 1 deletion(-)
+ src/3rdparty/angle/src/libGLESv2/main.cpp    | 10 ++++++++--
+ 3 files changed, 19 insertions(+), 3 deletions(-)
 
 diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h
 index c9e6f17..1ac2d3f 100644
@@ -28,7 +28,7 @@ index c9e6f17..1ac2d3f 100644
  #elif defined (__SYMBIAN32__)
  #   define KHRONOS_APICALL IMPORT_C
 diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp
-index 0f8439c..8a1baef 100644
+index d1489f2..e88cad7 100644
 --- a/src/3rdparty/angle/src/libEGL/main.cpp
 +++ b/src/3rdparty/angle/src/libEGL/main.cpp
 @@ -49,6 +49,8 @@ void DeallocateCurrent()
@@ -40,7 +40,7 @@ index 0f8439c..8a1baef 100644
  extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
  {
      switch (reason)
-@@ -100,16 +102,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
+@@ -108,16 +110,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
      return TRUE;
  }
  
@@ -64,26 +64,27 @@ index 0f8439c..8a1baef 100644
 +#endif
  }
  
- void setCurrentError(EGLint error)
+ void recordError(const Error &error)
 diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp
-index 4444d1a..1c577bc 100644
+index 3ac00d5..00f63ae 100644
 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/main.cpp
-@@ -46,6 +46,8 @@ void DeallocateCurrent()
+@@ -74,7 +74,7 @@ void DeallocateCurrent()
  
  }
  
-+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
-+
+-#ifdef ANGLE_PLATFORM_WINDOWS
++#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC)
  extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
  {
      switch (reason)
-@@ -82,16 +84,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
+@@ -117,18 +117,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
+ 
      return TRUE;
  }
+-#endif
++#endif // ANGLE_PLATFORM_WINDOWS && !QT_OPENGL_ES_2_ANGLE_STATIC
  
-+#endif // !QT_OPENGL_ES_2_ANGLE_STATIC
-+
  namespace gl
  {
  
@@ -104,5 +105,5 @@ index 4444d1a..1c577bc 100644
  
  void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
 -- 
-1.9.0.msysgit.0
+1.9.4.msysgit.1
 
diff --git a/src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch b/src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch
deleted file mode 100644
index 78c3e0fbe8d..00000000000
--- a/src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch
+++ /dev/null
@@ -1,84 +0,0 @@
-From df225c023963f37737b7e2d020c8f89a5d5f878e Mon Sep 17 00:00:00 2001
-From: Andy Shaw <andy.shaw@digia.com>
-Date: Tue, 16 Sep 2014 23:49:50 +0300
-Subject: [PATCH 05/16] Fix build when SSE2 is not available.
-
-Although SSE2 support is detected at runtime it still may not be
-available at build time, so we have to ensure it only uses SSE2
-when it is available at build time too.
-
-Change-Id: I86c45a6466ab4cec79aa0f62b0d5230a78ad825a
----
- src/3rdparty/angle/src/common/mathutil.h                    | 2 ++
- src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp | 8 ++++++++
- 2 files changed, 10 insertions(+)
-
-diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h
-index ffcb908..52f2bc1 100644
---- a/src/3rdparty/angle/src/common/mathutil.h
-+++ b/src/3rdparty/angle/src/common/mathutil.h
-@@ -118,6 +118,7 @@ inline bool supportsSSE2()
-         return supports;
-     }
- 
-+#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid()
-     int info[4];
-     __cpuid(info, 0);
- 
-@@ -127,6 +128,7 @@ inline bool supportsSSE2()
- 
-         supports = (info[3] >> 26) & 1;
-     }
-+#endif
- 
-     checked = true;
- 
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp
-index cc20d94..f777b30 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp
-@@ -10,6 +10,10 @@
- 
- #include "libGLESv2/renderer/loadimage.h"
- 
-+#if !defined(__SSE2__) && (defined(_M_X64) || _M_IX86_FP == 2)
-+#define __SSE2__
-+#endif
-+
- namespace rx
- {
- 
-@@ -17,6 +21,7 @@ void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
-                         const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
-                         uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
- {
-+#ifdef __SSE2__
-     __m128i zeroWide = _mm_setzero_si128();
- 
-     for (size_t z = 0; z < depth; z++)
-@@ -54,12 +59,14 @@ void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
-             }
-         }
-     }
-+#endif
- }
- 
- void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
-                            const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
-                            uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
- {
-+#ifdef __SSE2__
-     __m128i brMask = _mm_set1_epi32(0x00ff00ff);
- 
-     for (size_t z = 0; z < depth; z++)
-@@ -99,6 +106,7 @@ void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
-             }
-         }
-     }
-+#endif
- }
- 
- }
--- 
-1.9.0.msysgit.0
-
diff --git a/src/angle/patches/0006-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch b/src/angle/patches/0006-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch
deleted file mode 100644
index e60bebd2335..00000000000
--- a/src/angle/patches/0006-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From 2a8568e6f44731df96f6567ffcc59a65ad2b3f29 Mon Sep 17 00:00:00 2001
-From: Kai Koehne <kai.koehne@digia.com>
-Date: Tue, 16 Sep 2014 23:55:25 +0300
-Subject: [PATCH 06/16] Fix compilation of libGLESv2 with older MinGW-w64
- headers
-
-Fix compilation of libGLESv2 for mingw-headers predating MinGW-w64
-svn commit 5567 (like MinGW-builds gcc 4.7.2-rev8, the toolchain
-we officially support).
-
-Commit 5567 added the D3DCOMPILER_DLL define to d3dcompiler.h, but with
-a trailing semicolon that has then fixed in commit 5783. Any toolchain
-that ships MinGW-w64 headers from a version in between (like
-MinGW-builds gcc 4.7.2-rev11) will unfortunately remain broken.
-
-Change-Id: I31272a1a991c4fc0f1611f8fb7510be51d6bb925
----
- .../angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp     | 15 +++++++++++++++
- 1 file changed, 15 insertions(+)
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-index acbd852..eb0dfa5 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-@@ -10,6 +10,21 @@
- 
- #include "common/utilities.h"
- 
-+#if defined(__MINGW32__) && !defined(D3DCOMPILER_DLL)
-+
-+// Add define + typedefs for older MinGW-w64 headers (pre 5783)
-+
-+#define D3DCOMPILER_DLL L"d3dcompiler_43.dll"
-+
-+HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename,
-+        const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
-+        const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages);
-+typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const char *filename,
-+        const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
-+        const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages);
-+
-+#endif // __MINGW32__ && !D3DCOMPILER_DLL
-+
- namespace rx
- {
- 
--- 
-1.9.0.msysgit.0
-
diff --git a/src/angle/patches/0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch b/src/angle/patches/0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch
deleted file mode 100644
index c796ebc95e3..00000000000
--- a/src/angle/patches/0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 76152feea8265f40fec8c6e53f976dbd82fb6c80 Mon Sep 17 00:00:00 2001
-From: Thiago Macieira <thiago.macieira@intel.com>
-Date: Tue, 16 Sep 2014 23:56:43 +0300
-Subject: [PATCH 07/16] Fix ANGLE build with Microsoft Visual Studio "14" CTP
-
-This version has a few new C99 support added, including snprintf.
-
-Change-Id: I5776456fd94254a64f08791f59bc775cb24c9b7f
----
- src/3rdparty/angle/src/common/angleutils.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h
-index 50a4132..ddbbd5f 100644
---- a/src/3rdparty/angle/src/common/angleutils.h
-+++ b/src/3rdparty/angle/src/common/angleutils.h
-@@ -135,7 +135,7 @@ inline std::string Str(int i)
- std::string FormatString(const char *fmt, va_list vararg);
- std::string FormatString(const char *fmt, ...);
- 
--#if defined(_MSC_VER)
-+#if defined(_MSC_VER) && _MSC_VER < 1900
- #define snprintf _snprintf
- #endif
- 
--- 
-1.9.0.msysgit.0
-
diff --git a/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch b/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch
index 7c821580d04..801db67682a 100644
--- a/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch
+++ b/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch
@@ -1,6 +1,6 @@
-From 4f6dd1f7cdce3340723cc23e0aea27b156fa3497 Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@digia.com>
-Date: Tue, 16 Sep 2014 23:59:40 +0300
+From 4a5960465d1632ab089320fcbba4af294d58fd9a Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@theqtcompany.com>
+Date: Fri, 7 Nov 2014 14:05:36 +0200
 Subject: [PATCH 08/16] ANGLE: Dynamically load D3D compiler from a list or the
  environment
 
@@ -11,29 +11,28 @@ QT_D3DCOMPILER_DLL.
 
 Change-Id: I0d7a8a8a36cc571836f8fa59ea14513b9b19c19b
 ---
- .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp    | 27 +++++++++++++++++++---
- 1 file changed, 24 insertions(+), 3 deletions(-)
+ .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp    | 27 ++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
 
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-index eb0dfa5..5715d5f 100644
+index bfeaf51..9d003b4 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-@@ -25,6 +25,10 @@ typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const
- 
- #endif // __MINGW32__ && !D3DCOMPILER_DLL
+@@ -11,6 +11,10 @@
+ #include "common/features.h"
+ #include "common/utilities.h"
  
 +#ifndef QT_D3DCOMPILER_DLL
 +#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL
 +#endif
 +
- namespace rx
+ // Definitions local to the translation unit
+ namespace
  {
- 
-@@ -59,10 +63,27 @@ bool HLSLCompiler::initialize()
+@@ -132,6 +136,29 @@ bool HLSLCompiler::initialize()
      }
  #endif  // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
  
--    if (!mD3DCompilerModule)
 +    // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL
 +    const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL");
 +    if (!defaultCompiler)
@@ -51,15 +50,15 @@ index eb0dfa5..5715d5f 100644
 +
 +    // Load the first available known compiler DLL
 +    for (int i = 0; compilerDlls[i]; ++i)
-     {
--        // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
--        mD3DCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
++    {
 +        mD3DCompilerModule = LoadLibrary(compilerDlls[i]);
 +        if (mD3DCompilerModule)
 +            break;
-     }
- 
++    }
++
      if (!mD3DCompilerModule)
+     {
+         // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
 -- 
-1.9.0.msysgit.0
+1.9.4.msysgit.1
 
diff --git a/src/angle/patches/0009-ANGLE-Support-WinRT.patch b/src/angle/patches/0009-ANGLE-Support-WinRT.patch
index f4bae46b630..a38fb4ea13c 100644
--- a/src/angle/patches/0009-ANGLE-Support-WinRT.patch
+++ b/src/angle/patches/0009-ANGLE-Support-WinRT.patch
@@ -1,1126 +1,673 @@
-From 7ff7dd46f54e23ae309887366bf477de9c33005b Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@digia.com>
-Date: Wed, 17 Sep 2014 00:58:29 +0300
+From 4d150ba3814f824f1cadaedbdb83d0ac79d0e1a2 Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@theqtcompany.com>
+Date: Fri, 14 Nov 2014 09:28:11 +0200
 Subject: [PATCH 09/16] ANGLE: Support WinRT
 
-This enables EGL for WinRT's native types, and adjusts some codepaths
-to accommodate differences between desktop Windows and WinRT.
+Tweak ANGLE's existing support for WinRT to allow for changing the
+window size on Windows Phone.
 
-- WinRT native handles added to eglplatform.h
-- References to native handles in libEGL/libGLESv2 follow eglplatform.h
-- D3D 11.1 structures and methods used when necessary
-- TLS replaced with thread attribute
-- LocalAlloc/Free replaced with Heap API
-
-Change-Id: Ia90377e700d335a1c569c2145008dd4b0dfd84d3
-Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
+Change-Id: Ia312b5318b977838a2953f1f530487cbf24974bc
 ---
- src/3rdparty/angle/include/EGL/eglplatform.h       |  10 +-
- src/3rdparty/angle/src/common/platform.h           |   3 +
- src/3rdparty/angle/src/common/tls.cpp              |  37 ++++-
- src/3rdparty/angle/src/common/tls.h                |   6 +-
- src/3rdparty/angle/src/common/utilities.cpp        |  51 +++++-
- src/3rdparty/angle/src/libEGL/Display.cpp          |  13 +-
- src/3rdparty/angle/src/libEGL/Display.h            |   6 +-
- src/3rdparty/angle/src/libEGL/Surface.cpp          | 185 ++++++++++++++++++++-
- src/3rdparty/angle/src/libEGL/Surface.h            |  37 ++++-
- src/3rdparty/angle/src/libEGL/libEGL.cpp           |   8 +-
- src/3rdparty/angle/src/libEGL/main.cpp             |  21 +++
- src/3rdparty/angle/src/libGLESv2/main.cpp          |  20 +++
- src/3rdparty/angle/src/libGLESv2/main.h            |   4 +
- .../angle/src/libGLESv2/renderer/Renderer.h        |   2 +-
- .../angle/src/libGLESv2/renderer/SwapChain.h       |  15 +-
- .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp    |  11 +-
- .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp    |  13 +-
- .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h  |   4 +-
- .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp   |  73 ++++++--
- .../src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h |   6 +-
- .../src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp |   2 +-
- .../src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h   |   2 +-
- 22 files changed, 481 insertions(+), 48 deletions(-)
+ src/3rdparty/angle/include/EGL/eglplatform.h       |  5 +-
+ src/3rdparty/angle/src/common/NativeWindow.h       |  7 +-
+ src/3rdparty/angle/src/common/platform.h           |  4 +-
+ .../angle/src/common/win32/NativeWindow.cpp        |  2 +-
+ .../src/common/winrt/CoreWindowNativeWindow.cpp    | 87 +++++++++++++---------
+ .../src/common/winrt/CoreWindowNativeWindow.h      | 48 ++----------
+ .../src/common/winrt/InspectableNativeWindow.cpp   |  8 +-
+ .../src/common/winrt/InspectableNativeWindow.h     |  7 +-
+ .../common/winrt/SwapChainPanelNativeWindow.cpp    |  2 +-
+ .../src/common/winrt/SwapChainPanelNativeWindow.h  |  2 +-
+ src/3rdparty/angle/src/libEGL/Display.h            |  1 +
+ src/3rdparty/angle/src/libEGL/Surface.cpp          | 45 ++++++++---
+ src/3rdparty/angle/src/libEGL/Surface.h            |  4 +
+ src/3rdparty/angle/src/libEGL/libEGL.cpp           | 20 +++++
+ .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h  |  2 +-
+ .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp   | 74 +++++++++++-------
+ .../src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h |  2 +
+ 17 files changed, 189 insertions(+), 131 deletions(-)
 
 diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h
-index 3ab8844..ea9f577 100644
+index 3793e57..2eb3674 100644
 --- a/src/3rdparty/angle/include/EGL/eglplatform.h
 +++ b/src/3rdparty/angle/include/EGL/eglplatform.h
-@@ -67,7 +67,15 @@
-  * implementations.
-  */
+@@ -73,13 +73,14 @@
+ #endif
+ #include <windows.h>
+ 
+-typedef HDC     EGLNativeDisplayType;
+ typedef HBITMAP EGLNativePixmapType;
+ 
+-#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP /* Windows Store */
++#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */
+ #include <inspectable.h>
++typedef IInspectable* EGLNativeDisplayType;
+ typedef IInspectable* EGLNativeWindowType;
+ #else
++typedef HDC     EGLNativeDisplayType;
+ typedef HWND    EGLNativeWindowType;
+ #endif
  
--#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
-+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) /* Windows Runtime */
-+
-+struct IUnknown;
-+
-+typedef IUnknown *EGLNativeDisplayType;
-+typedef void     *EGLNativePixmapType;
-+typedef IUnknown *EGLNativeWindowType;
+diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/common/NativeWindow.h
+index dc5fc8f..9e93aea 100644
+--- a/src/3rdparty/angle/src/common/NativeWindow.h
++++ b/src/3rdparty/angle/src/common/NativeWindow.h
+@@ -44,10 +44,11 @@ typedef IDXGIFactory DXGIFactory;
+ 
+ namespace rx
+ {
 +
-+#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
- #ifndef WIN32_LEAN_AND_MEAN
- #define WIN32_LEAN_AND_MEAN 1
- #endif
+ class NativeWindow
+ {
+-  public:
+-    explicit NativeWindow(EGLNativeWindowType window);
++public:
++    explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display);
+ 
+     bool initialize();
+     bool getClientRect(LPRECT rect);
+@@ -58,9 +59,11 @@ class NativeWindow
+                             DXGISwapChain** swapChain);
+ 
+     inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
++    inline EGLNativeDisplayType getNativeDisplay() const { return mDisplay; }
+ 
+   private:
+     EGLNativeWindowType mWindow;
++    EGLNativeDisplayType mDisplay;
+ 
+ #if defined(ANGLE_ENABLE_WINDOWS_STORE)
+     std::shared_ptr<InspectableNativeWindow> mImpl;
 diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
-index d07297d..387ba41 100644
+index cd12dba..0065ec7 100644
 --- a/src/3rdparty/angle/src/common/platform.h
 +++ b/src/3rdparty/angle/src/common/platform.h
-@@ -11,6 +11,9 @@
- 
- #if defined(_WIN32) || defined(_WIN64)
- #   define ANGLE_PLATFORM_WINDOWS 1
-+#   if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
-+#      define ANGLE_PLATFORM_WINRT 1
-+#   endif
- #elif defined(__APPLE__)
- #   define ANGLE_PLATFORM_APPLE 1
- #   define ANGLE_PLATFORM_POSIX 1
-diff --git a/src/3rdparty/angle/src/common/tls.cpp b/src/3rdparty/angle/src/common/tls.cpp
-index 6b78219..c46fab5 100644
---- a/src/3rdparty/angle/src/common/tls.cpp
-+++ b/src/3rdparty/angle/src/common/tls.cpp
-@@ -10,11 +10,28 @@
- 
- #include <assert.h>
- 
-+#if defined(ANGLE_PLATFORM_WINRT)
-+#include <vector>
-+std::vector<void *> *tls = nullptr;
-+std::vector<TLSIndex> *freeIndices = nullptr;
-+#endif
-+
- TLSIndex CreateTLSIndex()
- {
-     TLSIndex index;
- 
--#ifdef ANGLE_PLATFORM_WINDOWS
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    if (!tls)
-+        tls = new std::vector<void *>;
-+    if (freeIndices && !freeIndices->empty()) {
-+        index = freeIndices->back();
-+        freeIndices->pop_back();
-+        return index;
-+    } else {
-+        tls->push_back(nullptr);
-+        return tls->size() - 1;
-+    }
-+#elif defined(ANGLE_PLATFORM_WINDOWS)
-     index = TlsAlloc();
- #elif defined(ANGLE_PLATFORM_POSIX)
-     // Create global pool key
-@@ -36,7 +53,12 @@ bool DestroyTLSIndex(TLSIndex index)
-         return false;
-     }
+@@ -34,7 +34,7 @@
+ #endif
  
--#ifdef ANGLE_PLATFORM_WINDOWS
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    if (!freeIndices)
-+        freeIndices = new std::vector<TLSIndex>;
-+    freeIndices->push_back(index);
-+    return true;
-+#elif ANGLE_PLATFORM_WINDOWS
-     return (TlsFree(index) == TRUE);
- #elif defined(ANGLE_PLATFORM_POSIX)
-     return (pthread_key_delete(index) == 0);
-@@ -51,7 +73,10 @@ bool SetTLSValue(TLSIndex index, void *value)
-         return false;
-     }
+ #ifdef ANGLE_PLATFORM_WINDOWS
+-#   if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP
++#   if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ #       define ANGLE_ENABLE_WINDOWS_STORE 1
+ #   endif
+ #   ifndef STRICT
+@@ -67,7 +67,9 @@
+ #   if defined(ANGLE_ENABLE_WINDOWS_STORE)
+ #       include <dxgi1_3.h>
+ #       if defined(_DEBUG)
++#          if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
+ #           include <DXProgrammableCapture.h>
++#          endif
+ #           include <dxgidebug.h>
+ #       endif
+ #   endif
+diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp
+index aa2bfa4..2440747 100644
+--- a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp
++++ b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp
+@@ -16,7 +16,7 @@ bool IsValidEGLNativeWindowType(EGLNativeWindowType window)
+     return (IsWindow(window) == TRUE);
+ }
  
--#ifdef ANGLE_PLATFORM_WINDOWS
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    tls->at(index) = value;
-+    return true;
-+#elif defined(ANGLE_PLATFORM_WINDOWS)
-     return (TlsSetValue(index, value) == TRUE);
- #elif defined(ANGLE_PLATFORM_POSIX)
-     return (pthread_setspecific(index, value) == 0);
-@@ -60,13 +85,17 @@ bool SetTLSValue(TLSIndex index, void *value)
- 
- void *GetTLSValue(TLSIndex index)
+-NativeWindow::NativeWindow(EGLNativeWindowType window) : mWindow(window)
++NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) : mWindow(window), mDisplay(display)
  {
-+#if !defined(ANGLE_PLATFORM_WINRT) // Valid on WinRT, as Alloc handles the index creation
-     assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index");
-+#endif
-     if (index == TLS_INVALID_INDEX)
-     {
-         return NULL;
-     }
+ }
  
--#ifdef ANGLE_PLATFORM_WINDOWS
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    return tls->at(index);
-+#elif defined(ANGLE_PLATFORM_WINDOWS)
-     return TlsGetValue(index);
- #elif defined(ANGLE_PLATFORM_POSIX)
-     return pthread_getspecific(index);
-diff --git a/src/3rdparty/angle/src/common/tls.h b/src/3rdparty/angle/src/common/tls.h
-index 4b25fbc..c40ae1a 100644
---- a/src/3rdparty/angle/src/common/tls.h
-+++ b/src/3rdparty/angle/src/common/tls.h
-@@ -11,7 +11,11 @@
- 
- #include "common/platform.h"
- 
--#ifdef ANGLE_PLATFORM_WINDOWS
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    typedef size_t TLSIndex;
-+#   define TLS_OUT_OF_INDEXES (static_cast<TLSIndex>(-1))
-+#   define TLS_INVALID_INDEX TLS_OUT_OF_INDEXES
-+#elif defined(ANGLE_PLATFORM_WINDOWS)
-     typedef DWORD TLSIndex;
- #   define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES)
- #elif defined(ANGLE_PLATFORM_POSIX)
-diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp
-index 405f119..4b8e325 100644
---- a/src/3rdparty/angle/src/common/utilities.cpp
-+++ b/src/3rdparty/angle/src/common/utilities.cpp
-@@ -9,6 +9,14 @@
- #include "common/utilities.h"
- #include "common/mathutil.h"
- #include "common/platform.h"
-+#if defined(ANGLE_PLATFORM_WINRT)
-+#  include <locale>
-+#  include <codecvt>
-+#  include <wrl.h>
-+#  include <windows.storage.h>
-+   using namespace Microsoft::WRL;
-+   using namespace ABI::Windows::Storage;
-+#endif
+diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
+index 0e63fa5..9b65c15 100644
+--- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
++++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
+@@ -6,21 +6,25 @@
  
- #include <set>
+ // CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types.
  
-@@ -441,7 +449,48 @@ int VariableSortOrder(GLenum type)
+-#include <windows.graphics.display.h>
++#include <algorithm>
+ #include "common/winrt/CoreWindowNativeWindow.h"
+ using namespace ABI::Windows::Foundation::Collections;
  
- std::string getTempPath()
+ namespace rx
  {
--#ifdef ANGLE_PLATFORM_WINDOWS
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    static std::string path;
-+
-+    while (path.empty())
-+    {
-+        ComPtr<IApplicationDataStatics> factory;
-+        Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData);
-+        HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory));
-+        if (FAILED(result))
-+            break;
 +
-+        ComPtr<IApplicationData> applicationData;
-+        result = factory->get_Current(&applicationData);
-+        if (FAILED(result))
-+            break;
++typedef ITypedEventHandler<ABI::Windows::UI::Core::CoreWindow *, ABI::Windows::UI::Core::WindowSizeChangedEventArgs *> SizeChangedHandler;
 +
-+        ComPtr<IStorageFolder> storageFolder;
-+        result = applicationData->get_LocalFolder(&storageFolder);
-+        if (FAILED(result))
-+            break;
+ CoreWindowNativeWindow::~CoreWindowNativeWindow()
+ {
+     unregisterForSizeChangeEvents();
+ }
+ 
+-bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
++bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet)
+ {
+     ComPtr<IPropertySet> props = propertySet;
+     ComPtr<IInspectable> win = window;
++    ComPtr<IInspectable> displayInformation = display;
+     SIZE swapChainSize = {};
+     bool swapChainSizeSpecified = false;
+     HRESULT result = S_OK;
+@@ -47,6 +51,29 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet
+ 
+     if (SUCCEEDED(result))
+     {
++        result = displayInformation.As(&mDisplayInformation);
++    }
 +
-+        ComPtr<IStorageItem> localFolder;
-+        result = storageFolder.As(&localFolder);
-+        if (FAILED(result))
-+            break;
++    if (SUCCEEDED(result))
++    {
++#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
++        ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation2> displayInformation2;
++        result = mDisplayInformation.As(&displayInformation2);
++        ASSERT(SUCCEEDED(result));
 +
-+        HSTRING localFolderPath;
-+        result = localFolder->get_Path(&localFolderPath);
-+        if (FAILED(result))
-+            break;
++        result = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor);
++        ASSERT(SUCCEEDED(result));
++#else
++        ABI::Windows::Graphics::Display::ResolutionScale resolutionScale;
++        result = mDisplayInformation->get_ResolutionScale(&resolutionScale);
++        ASSERT(SUCCEEDED(result));
 +
-+        std::wstring_convert< std::codecvt_utf8<wchar_t> > converter;
-+        path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL));
-+        if (path.empty())
-+        {
-+            UNREACHABLE();
-+            break;
-+        }
++        mScaleFactor = DOUBLE(resolutionScale) / 100.0;
++#endif
 +    }
 +
-+    return path;
-+#elif defined(ANGLE_PLATFORM_WINDOWS)
-     char path[MAX_PATH];
-     DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
-     if (pathLen == 0)
-diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp
-index aaebdb3..ba09631 100644
---- a/src/3rdparty/angle/src/libEGL/Display.cpp
-+++ b/src/3rdparty/angle/src/libEGL/Display.cpp
-@@ -56,6 +56,10 @@ Display::Display(EGLNativeDisplayType displayId, EGLint displayType)
-       mRequestedDisplayType(displayType),
-       mRenderer(NULL)
++    if (SUCCEEDED(result))
++    {
+         // If a swapchain size is specfied, then the automatic resize
+         // behaviors implemented by the host should be disabled.  The swapchain
+         // will be still be scaled when being rendered to fit the bounds
+@@ -60,7 +87,14 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet
+         }
+         else
+         {
+-            result = GetCoreWindowSizeInPixels(mCoreWindow, &mClientRect);
++            ABI::Windows::Foundation::Rect rect;
++            HRESULT result = mCoreWindow->get_Bounds(&rect);
++            if (SUCCEEDED(result))
++            {
++                LONG width = std::floor(rect.Width * mScaleFactor + 0.5);
++                LONG height = std::floor(rect.Height * mScaleFactor + 0.5);
++                mClientRect = { 0, 0, width, height };
++            }
+         }
+     }
+ 
+@@ -76,12 +110,8 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet
+ 
+ bool CoreWindowNativeWindow::registerForSizeChangeEvents()
  {
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    if (mDisplayId)
-+        mDisplayId->AddRef();
-+#endif
+-    ComPtr<IWindowSizeChangedEventHandler> sizeChangedHandler;
+-    HRESULT result = Microsoft::WRL::MakeAndInitialize<CoreWindowSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this());
+-    if (SUCCEEDED(result))
+-    {
+-        result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken);
+-    }
++    HRESULT result = mCoreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &CoreWindowNativeWindow::onSizeChanged).Get(),
++                                                  &mSizeChangedEventToken);
+ 
+     if (SUCCEEDED(result))
+     {
+@@ -126,7 +156,7 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor
+     if (SUCCEEDED(result))
+     {
+ 
+-#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
++#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected
+         // Test if swapchain supports resize.  On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED.  On
+         // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed
+         // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations.
+@@ -152,36 +182,19 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor
+     return result;
  }
  
- Display::~Display()
-@@ -68,6 +72,11 @@ Display::~Display()
+-HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow>& coreWindow, RECT *windowSize)
++// Basically, this shouldn't be used on Phone
++HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e)
+ {
+-    ABI::Windows::Foundation::Rect bounds;
+-    HRESULT result = coreWindow->get_Bounds(&bounds);
+-    if (SUCCEEDED(result))
++    ABI::Windows::Foundation::Size size;
++    if (SUCCEEDED(e->get_Size(&size)))
      {
-         displays->erase(iter);
+-        *windowSize = { 0, 0, ConvertDipsToPixels(bounds.Width), ConvertDipsToPixels(bounds.Height) };
++        SIZE windowSizeInPixels = {
++            std::floor(size.Width * mScaleFactor + 0.5),
++            std::floor(size.Height * mScaleFactor + 0.5)
++        };
++        setNewClientSize(windowSizeInPixels);
      }
-+
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    if (mDisplayId)
-+        mDisplayId->Release();
-+#endif
+ 
+-    return result;
+-}
+-
+-static float GetLogicalDpi()
+-{
+-    ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
+-    float dpi = 96.0f;
+-
+-    if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
+-    {
+-        if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
+-        {
+-            return dpi;
+-        }
+-    }
+-    return dpi;
+-}
+-
+-long ConvertDipsToPixels(float dips)
+-{
+-    static const float dipsPerInch = 96.0f;
+-    return lround((dips * GetLogicalDpi() / dipsPerInch));
++    return S_OK;
  }
+ }
+diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h
+index 0c6222d..1c55124 100644
+--- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h
++++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h
+@@ -11,67 +11,29 @@
+ 
+ #include "common/winrt/InspectableNativeWindow.h"
+ #include <memory>
+-
+-typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler;
++#include <windows.graphics.display.h>
+ 
+ namespace rx
+ {
+-long ConvertDipsToPixels(float dips);
  
- bool Display::initialize()
-@@ -192,7 +201,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
+ class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
+ {
+   public:
+     ~CoreWindowNativeWindow();
  
+-    bool initialize(EGLNativeWindowType window, IPropertySet *propertySet);
++    bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet);
+     bool registerForSizeChangeEvents();
+     void unregisterForSizeChangeEvents();
+     HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
  
+   private:
++    HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
++
+     ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
++    ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation;
+     ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
+ };
  
--EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList)
-+EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList)
- {
-     const Config *configuration = mConfigSet.get(config);
-     EGLint postSubBufferSupported = EGL_FALSE;
-@@ -493,7 +502,7 @@ bool Display::isValidSurface(egl::Surface *surface)
-     return mSurfaceSet.find(surface) != mSurfaceSet.end();
+-[uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)]
+-class CoreWindowSizeChangedHandler :
+-    public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler>
+-{
+-  public:
+-    CoreWindowSizeChangedHandler() { }
+-    HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host)
+-    {
+-        if (!host)
+-        {
+-            return E_INVALIDARG;
+-        }
+-
+-        mHost = host;
+-        return S_OK;
+-    }
+-
+-    // IWindowSizeChangedEventHandler
+-    IFACEMETHOD(Invoke)(ABI::Windows::UI::Core::ICoreWindow *sender, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *sizeChangedEventArgs)
+-    {
+-        std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
+-        if (host)
+-        {
+-            ABI::Windows::Foundation::Size windowSize;
+-            if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize)))
+-            {
+-                SIZE windowSizeInPixels = { ConvertDipsToPixels(windowSize.Width), ConvertDipsToPixels(windowSize.Height) };
+-                host->setNewClientSize(windowSizeInPixels);
+-            }
+-        }
+-
+-        return S_OK;
+-    }
+-
+-  private:
+-    std::weak_ptr<InspectableNativeWindow> mHost;
+-};
+-
+-HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow>& coreWindow, RECT *windowSize);
  }
  
--bool Display::hasExistingWindowSurface(HWND window)
-+bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
+ #endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
+diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp
+index c062a48..0589f6d 100644
+--- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp
++++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp
+@@ -11,9 +11,9 @@
+ 
+ namespace rx
+ {
+-NativeWindow::NativeWindow(EGLNativeWindowType window)
++NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display)
++    : mWindow(window), mDisplay(display)
  {
-     for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
+-    mWindow = window;
+ }
+ 
+ bool NativeWindow::initialize()
+@@ -40,7 +40,7 @@ bool NativeWindow::initialize()
+         mImpl = std::make_shared<CoreWindowNativeWindow>();
+         if (mImpl)
+         {
+-            return mImpl->initialize(mWindow, propertySet.Get());
++            return mImpl->initialize(mWindow, mDisplay, propertySet.Get());
+         }
+     }
+     else if (IsSwapChainPanel(mWindow, &swapChainPanel))
+@@ -48,7 +48,7 @@ bool NativeWindow::initialize()
+         mImpl = std::make_shared<SwapChainPanelNativeWindow>();
+         if (mImpl)
+         {
+-            return mImpl->initialize(mWindow, propertySet.Get());
++            return mImpl->initialize(mWindow, mDisplay, propertySet.Get());
+         }
+     }
+     else
+diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h
+index c625348..402941a 100644
+--- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h
++++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h
+@@ -32,13 +32,14 @@ class InspectableNativeWindow
+         mRequiresSwapChainScaling(false),
+         mClientRectChanged(false),
+         mClientRect({0,0,0,0}),
+-        mNewClientRect({0,0,0,0})
++        mNewClientRect({0,0,0,0}),
++        mScaleFactor(1.0)
      {
-diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h
-index 250878f..73ba767 100644
---- a/src/3rdparty/angle/src/libEGL/Display.h
-+++ b/src/3rdparty/angle/src/libEGL/Display.h
-@@ -43,7 +43,7 @@ class Display
-     bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
-     bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
+         mSizeChangedEventToken.value = 0;
+     }
+     virtual ~InspectableNativeWindow(){}
+ 
+-    virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0;
++    virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0;
+     virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0;
+     virtual bool registerForSizeChangeEvents() = 0;
+     virtual void unregisterForSizeChangeEvents() = 0;
+@@ -49,6 +50,7 @@ class InspectableNativeWindow
+         if (mClientRectChanged && mSupportsSwapChainResize)
+         {
+             mClientRect = mNewClientRect;
++            mClientRectChanged = false;
+         }
+ 
+         *rect = mClientRect;
+@@ -76,6 +78,7 @@ protected:
+     RECT mClientRect;
+     RECT mNewClientRect;
+     bool mClientRectChanged;
++    DOUBLE mScaleFactor;
  
--    EGLSurface createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList);
-+    EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList);
-     EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList);
-     EGLContext createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
+     EventRegistrationToken mSizeChangedEventToken;
+ };
+diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp
+index 4e4fb6d..268dfbd 100644
+--- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp
++++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp
+@@ -18,7 +18,7 @@ SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow()
+     unregisterForSizeChangeEvents();
+ }
  
-@@ -54,7 +54,7 @@ class Display
-     bool isValidConfig(EGLConfig config);
-     bool isValidContext(gl::Context *context);
-     bool isValidSurface(egl::Surface *surface);
--    bool hasExistingWindowSurface(HWND window);
-+    bool hasExistingWindowSurface(EGLNativeWindowType window);
+-bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
++bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet)
+ {
+     ComPtr<IPropertySet> props = propertySet;
+     ComPtr<IInspectable> win = window;
+diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h
+index e88f554..5bbf274 100644
+--- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h
++++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h
+@@ -18,7 +18,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e
+   public:
+     ~SwapChainPanelNativeWindow();
  
-     rx::Renderer *getRenderer() { return mRenderer; };
+-    bool initialize(EGLNativeWindowType window, IPropertySet *propertySet);
++    bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet);
+     bool registerForSizeChangeEvents();
+     void unregisterForSizeChangeEvents();
+     HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
+diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h
+index 378323a..b3ffcc8 100644
+--- a/src/3rdparty/angle/src/libEGL/Display.h
++++ b/src/3rdparty/angle/src/libEGL/Display.h
+@@ -67,6 +67,7 @@ class Display
  
-@@ -65,6 +65,8 @@ class Display
      const char *getExtensionString() const;
      const char *getVendorString() const;
- 
 +    EGLNativeDisplayType getDisplayId() const { return mDisplayId; }
-+
+ 
    private:
      DISALLOW_COPY_AND_ASSIGN(Display);
- 
 diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp
-index 13b0f20..fa79961 100644
+index 3414656..b664a85 100644
 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp
 +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp
-@@ -22,10 +22,20 @@
- #include "libEGL/main.h"
- #include "libEGL/Display.h"
- 
-+#if defined(ANGLE_PLATFORM_WINRT)
-+#  include "wrl.h"
-+#  include "windows.graphics.display.h"
-+#  include "windows.ui.core.h"
-+using namespace ABI::Windows::Graphics::Display;
-+using namespace ABI::Windows::Foundation;
-+using namespace ABI::Windows::UI::Core;
-+using namespace Microsoft::WRL;
-+#endif
-+
- namespace egl
+@@ -31,7 +31,7 @@ namespace egl
  {
  
--Surface::Surface(Display *display, const Config *config, HWND window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) 
-+Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported)
-     : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
+ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) 
+-    : mDisplay(display), mConfig(config), mNativeWindow(window), mPostSubBufferSupported(postSubBufferSupported)
++    : mDisplay(display), mConfig(config), mNativeWindow(window, display->getDisplayId()), mPostSubBufferSupported(postSubBufferSupported)
  {
-     mRenderer = mDisplay->getRenderer();
-@@ -43,6 +53,17 @@ Surface::Surface(Display *display, const Config *config, HWND window, EGLint fix
+     //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
+     mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
+@@ -47,6 +47,8 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win
+     mSwapInterval = -1;
+     mWidth = width;
      mHeight = height;
++    mFixedWidth = mWidth;
++    mFixedHeight = mHeight;
      setSwapInterval(1);
      mFixedSize = fixedSize;
-+    mSwapFlags = rx::SWAP_NORMAL;
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    if (mWindow)
-+        mWindow->AddRef();
-+    mScaleFactor = 1.0;
-+    mSizeToken.value = 0;
-+    mDpiToken.value = 0;
-+#   if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-+    mOrientationToken.value = 0;
-+#   endif
-+#endif
  
-     subclassWindow();
+@@ -54,7 +56,7 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win
  }
-@@ -64,16 +85,86 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL
+ 
+ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
+-    : mDisplay(display), mNativeWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
++    : mDisplay(display), mNativeWindow(NULL, NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
+ {
+     //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
+     mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
+@@ -71,6 +73,8 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL
      setSwapInterval(1);
      // This constructor is for offscreen surfaces, which are always fixed-size.
      mFixedSize = EGL_TRUE;
-+    mSwapFlags = rx::SWAP_NORMAL;
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    mScaleFactor = 1.0;
-+    mSizeToken.value = 0;
-+    mDpiToken.value = 0;
-+#   if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-+    mOrientationToken.value = 0;
-+#   endif
-+#endif
++    mFixedWidth = mWidth;
++    mFixedHeight = mHeight;
  }
  
  Surface::~Surface()
- {
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    if (mSizeToken.value) {
-+        ComPtr<ICoreWindow> coreWindow;
-+        HRESULT hr = mWindow->QueryInterface(coreWindow.GetAddressOf());
-+        ASSERT(SUCCEEDED(hr));
-+
-+        hr = coreWindow->remove_SizeChanged(mSizeToken);
-+        ASSERT(SUCCEEDED(hr));
-+    }
-+    if (mDpiToken.value) {
-+        ComPtr<IDisplayInformation> displayInformation;
-+        HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf());
-+        ASSERT(SUCCEEDED(hr));
-+
-+        hr = displayInformation->remove_DpiChanged(mDpiToken);
-+        ASSERT(SUCCEEDED(hr));
-+    }
-+#   if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
-+    if (mOrientationToken.value) {
-+        ComPtr<IDisplayInformation> displayInformation;
-+        HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf());
-+        ASSERT(SUCCEEDED(hr));
-+
-+        hr = displayInformation->remove_OrientationChanged(mOrientationToken);
-+        ASSERT(SUCCEEDED(hr));
-+    }
-+#   endif
-+#endif
-     unsubclassWindow();
-     release();
- }
+@@ -157,10 +161,13 @@ Error Surface::resetSwapChain()
  
- bool Surface::initialize()
+ Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight)
  {
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    if (!mFixedSize) {
-+        HRESULT hr;
-+        ComPtr<IDisplayInformation> displayInformation;
-+        hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf());
-+        ASSERT(SUCCEEDED(hr));
-+        onDpiChanged(displayInformation.Get(), 0);
-+        hr = displayInformation->add_DpiChanged(Callback<ITypedEventHandler<DisplayInformation *, IInspectable *>>(this, &Surface::onDpiChanged).Get(),
-+                                                &mDpiToken);
-+        ASSERT(SUCCEEDED(hr));
-+
-+#   if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-+        onOrientationChanged(displayInformation.Get(), 0);
-+        hr = displayInformation->add_OrientationChanged(Callback<ITypedEventHandler<DisplayInformation *, IInspectable *>>(this, &Surface::onOrientationChanged).Get(),
-+                                                        &mOrientationToken);
-+        ASSERT(SUCCEEDED(hr));
-+#   endif
-+
-+        ComPtr<ICoreWindow> coreWindow;
-+        hr = mWindow->QueryInterface(coreWindow.GetAddressOf());
-+        ASSERT(SUCCEEDED(hr));
-+
-+        Rect rect;
-+        hr = coreWindow->get_Bounds(&rect);
-+        ASSERT(SUCCEEDED(hr));
-+        mWidth = rect.Width * mScaleFactor;
-+        mHeight = rect.Height * mScaleFactor;
-+        hr = coreWindow->add_SizeChanged(Callback<ITypedEventHandler<CoreWindow *, WindowSizeChangedEventArgs *>>(this, &Surface::onSizeChanged).Get(),
-+                                         &mSizeToken);
-+        ASSERT(SUCCEEDED(hr));
-+    }
-+#endif
-+
-     if (!resetSwapChain())
-       return false;
+-    ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
+     ASSERT(mSwapChain);
  
-@@ -90,6 +181,11 @@ void Surface::release()
-         mTexture->releaseTexImage();
-         mTexture = NULL;
-     }
-+
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    if (mWindow)
-+        mWindow->Release();
+-    EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight));
++#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
++    backbufferWidth = std::max(1, backbufferWidth);
++    backbufferHeight = std::max(1, backbufferHeight);
 +#endif
- }
- 
- bool Surface::resetSwapChain()
-@@ -99,6 +195,7 @@ bool Surface::resetSwapChain()
-     int width;
-     int height;
++    EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight);
  
-+#if !defined(ANGLE_PLATFORM_WINRT)
-     if (!mFixedSize)
+     if (status == EGL_CONTEXT_LOST)
      {
-         RECT windowRect;
-@@ -114,6 +211,7 @@ bool Surface::resetSwapChain()
-         height = windowRect.bottom - windowRect.top;
+@@ -209,14 +216,14 @@ Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+         return Error(EGL_SUCCESS);
      }
-     else
-+#endif
+ 
+-    if (x + width > mWidth)
++    if (x + width > abs(mWidth))
      {
-         // non-window surface - size is determined at creation
-         width = mWidth;
-@@ -207,7 +305,7 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
-         return true;
+-        width = mWidth - x;
++        width = abs(mWidth) - x;
      }
  
--    EGLint status = mSwapChain->swapRect(x, y, width, height);
-+    EGLint status = mSwapChain->swapRect(x, y, width, height, mSwapFlags);
- 
-     if (status == EGL_CONTEXT_LOST)
+-    if (y + height > mHeight)
++    if (y + height > abs(mHeight))
      {
-@@ -224,7 +322,7 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
-     return true;
- }
- 
--HWND Surface::getWindowHandle()
-+EGLNativeWindowType Surface::getWindowHandle()
- {
-     return mWindow;
- }
-@@ -233,6 +331,7 @@ HWND Surface::getWindowHandle()
- #define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
- #define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
- 
-+#if !defined(ANGLE_PLATFORM_WINRT)
- static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
- {
-   if (message == WM_SIZE)
-@@ -246,9 +345,11 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam
-   WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
-   return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
- }
-+#endif
+-        height = mHeight - y;
++        height = abs(mHeight) - y;
+     }
  
- void Surface::subclassWindow()
- {
-+#if !defined(ANGLE_PLATFORM_WINRT)
-     if (!mWindow)
-     {
-         return;
-@@ -272,10 +373,14 @@ void Surface::subclassWindow()
-     SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
-     SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
-     mWindowSubclassed = true;
-+#else
-+    mWindowSubclassed = false;
-+#endif
- }
+     if (width == 0 || height == 0)
+@@ -224,6 +231,9 @@ Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+         return Error(EGL_SUCCESS);
+     }
  
- void Surface::unsubclassWindow()
- {
-+#if !defined(ANGLE_PLATFORM_WINRT)
-     if(!mWindowSubclassed)
-     {
-         return;
-@@ -299,16 +404,18 @@ void Surface::unsubclassWindow()
-     RemoveProp(mWindow, kSurfaceProperty);
-     RemoveProp(mWindow, kParentWndProc);
-     mWindowSubclassed = false;
-+#endif
- }
++    ASSERT(width > 0);
++    ASSERT(height > 0);
++
+     EGLint status = mSwapChain->swapRect(x, y, width, height);
  
- bool Surface::checkForOutOfDateSwapChain()
- {
--    RECT client;
-     int clientWidth = getWidth();
-     int clientHeight = getHeight();
-     bool sizeDirty = false;
-+#if !defined(ANGLE_PLATFORM_WINRT)
-     if (!mFixedSize && !IsIconic(getWindowHandle()))
-     {
-+        RECT client;
-         // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized
-         // because that's not a useful size to render to.
-         if (!GetClientRect(getWindowHandle(), &client))
-@@ -322,6 +429,7 @@ bool Surface::checkForOutOfDateSwapChain()
-         clientHeight = client.bottom - client.top;
+     if (status == EGL_CONTEXT_LOST)
+@@ -352,6 +362,13 @@ bool Surface::checkForOutOfDateSwapChain()
          sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
      }
-+#endif
  
++    if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight))
++    {
++        clientWidth = mFixedWidth;
++        clientHeight = mFixedHeight;
++        sizeDirty = true;
++    }
++
      bool wasDirty = (mSwapIntervalDirty || sizeDirty);
  
-@@ -446,4 +554,73 @@ EGLenum Surface::getFormat() const
+     if (mSwapIntervalDirty)
+@@ -378,7 +395,7 @@ bool Surface::checkForOutOfDateSwapChain()
+ 
+ Error Surface::swap()
  {
-     return mConfig->mRenderTargetFormat;
+-    return swapRect(0, 0, mWidth, mHeight);
++    return swapRect(0, 0, abs(mWidth), abs(mHeight));
  }
-+
-+#if defined(ANGLE_PLATFORM_WINRT)
-+
-+HRESULT Surface::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *args)
+ 
+ Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+@@ -471,6 +488,16 @@ EGLint Surface::isFixedSize() const
+     return mFixedSize;
+ }
+ 
++void Surface::setFixedWidth(EGLint width)
 +{
-+    HRESULT hr;
-+    Size size;
-+    hr = args->get_Size(&size);
-+    ASSERT(SUCCEEDED(hr));
-+
-+    resizeSwapChain(std::floor(size.Width * mScaleFactor + 0.5),
-+                    std::floor(size.Height * mScaleFactor + 0.5));
-+
-+    if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
-+    {
-+        glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
-+    }
-+
-+    return S_OK;
++    mFixedWidth = width;
 +}
 +
-+HRESULT Surface::onDpiChanged(IDisplayInformation *displayInformation, IInspectable *)
++void Surface::setFixedHeight(EGLint height)
 +{
-+    HRESULT hr;
-+#   if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-+    ComPtr<IDisplayInformation2> displayInformation2;
-+    hr = displayInformation->QueryInterface(displayInformation2.GetAddressOf());
-+    ASSERT(SUCCEEDED(hr));
-+
-+    hr = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor);
-+    ASSERT(SUCCEEDED(hr));
-+#   else
-+    ResolutionScale resolutionScale;
-+    hr = displayInformation->get_ResolutionScale(&resolutionScale);
-+    ASSERT(SUCCEEDED(hr));
-+
-+    mScaleFactor = double(resolutionScale) / 100.0;
-+#   endif
-+    return S_OK;
++    mFixedHeight = height;
 +}
 +
-+#   if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
-+HRESULT Surface::onOrientationChanged(IDisplayInformation *displayInformation, IInspectable *)
-+{
-+    HRESULT hr;
-+    DisplayOrientations orientation;
-+    hr = displayInformation->get_CurrentOrientation(&orientation);
-+    ASSERT(SUCCEEDED(hr));
-+    switch (orientation) {
-+    default:
-+    case DisplayOrientations_Portrait:
-+        mSwapFlags = rx::SWAP_NORMAL;
-+        break;
-+    case DisplayOrientations_Landscape:
-+        mSwapFlags = rx::SWAP_ROTATE_90;
-+        break;
-+    case DisplayOrientations_LandscapeFlipped:
-+        mSwapFlags = rx::SWAP_ROTATE_270;
-+        break;
-+    case DisplayOrientations_PortraitFlipped:
-+        mSwapFlags = rx::SWAP_ROTATE_180;
-+        break;
-+    }
-+    return S_OK;
-+}
-+#   endif
-+
-+#endif
-+
- }
+ EGLenum Surface::getFormat() const
+ {
+     return mConfig->mRenderTargetFormat;
 diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h
-index 24c66b7..ebffce8fe 100644
+index 662fe21..46382d0 100644
 --- a/src/3rdparty/angle/src/libEGL/Surface.h
 +++ b/src/3rdparty/angle/src/libEGL/Surface.h
-@@ -15,6 +15,20 @@
- 
- #include "common/angleutils.h"
- 
-+#if defined(ANGLE_PLATFORM_WINRT)
-+#include <EventToken.h>
-+namespace ABI { namespace Windows {
-+    namespace UI { namespace Core {
-+        struct ICoreWindow;
-+        struct IWindowSizeChangedEventArgs;
-+    } }
-+    namespace Graphics { namespace Display {
-+        struct IDisplayInformation;
-+    } }
-+} }
-+struct IInspectable;
-+#endif
-+
- namespace gl
- {
- class Texture2D;
-@@ -33,7 +47,7 @@ class Config;
- class Surface
- {
-   public:
--    Surface(Display *display, const egl::Config *config, HWND window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported);
-+    Surface(Display *display, const egl::Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported);
-     Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget);
- 
-     virtual ~Surface();
-@@ -42,7 +56,7 @@ class Surface
-     void release();
-     bool resetSwapChain();
- 
--    HWND getWindowHandle();
-+    EGLNativeWindowType getWindowHandle();
-     bool swap();
-     bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
- 
-@@ -71,6 +85,14 @@ class Surface
- private:
-     DISALLOW_COPY_AND_ASSIGN(Surface);
+@@ -70,6 +70,8 @@ class Surface
+     virtual gl::Texture2D *getBoundTexture() const;
  
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
-+    HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
-+#   if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-+    HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
-+#   endif
-+#endif
-+
-     Display *const mDisplay;
-     rx::Renderer *mRenderer;
+     EGLint isFixedSize() const;
++    void setFixedWidth(EGLint width);
++    void setFixedHeight(EGLint height);
  
-@@ -83,7 +105,7 @@ private:
-     bool resetSwapChain(int backbufferWidth, int backbufferHeight);
-     bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
- 
--    const HWND mWindow;            // Window that the surface is created for.
-+    const EGLNativeWindowType mWindow;            // Window that the surface is created for.
-     bool mWindowSubclassed;        // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
+   private:
+     DISALLOW_COPY_AND_ASSIGN(Surface);
+@@ -91,6 +93,8 @@ class Surface
      const egl::Config *mConfig;    // EGL config surface was created with
      EGLint mHeight;                // Height of surface
-@@ -104,9 +126,18 @@ private:
-     EGLint mSwapInterval;
-     EGLint mPostSubBufferSupported;
-     EGLint mFixedSize;
-+    EGLint mSwapFlags;
- 
-     bool mSwapIntervalDirty;
-     gl::Texture2D *mTexture;
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    double mScaleFactor;
-+    EventRegistrationToken mSizeToken;
-+    EventRegistrationToken mDpiToken;
-+#   if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-+    EventRegistrationToken mOrientationToken;
-+#   endif
-+#endif
- };
- }
- 
+     EGLint mWidth;                 // Width of surface
++    EGLint mFixedHeight;         // Pending height of the surface
++    EGLint mFixedWidth;          // Pending width of the surface
+ //  EGLint horizontalResolution;   // Horizontal dot pitch
+ //  EGLint verticalResolution;     // Vertical dot pitch
+ //  EGLBoolean largestPBuffer;     // If true, create largest pbuffer possible
 diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp
-index 7ce2b93..7ea11c5 100644
+index 6110698..dc20d85 100644
 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp
 +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp
-@@ -13,6 +13,7 @@
- 
- #include "common/debug.h"
- #include "common/version.h"
-+#include "common/platform.h"
- #include "libGLESv2/Context.h"
- #include "libGLESv2/Texture.h"
- #include "libGLESv2/main.h"
-@@ -120,12 +121,13 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis
-     }
- 
-     EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display);
--
-+#if !defined(ANGLE_PLATFORM_WINRT)
-     // Validate the display device context
-     if (WindowFromDC(displayId) == NULL)
-     {
-         return egl::success(EGL_NO_DISPLAY);
+@@ -706,6 +706,26 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint
+         return EGL_FALSE;
      }
-+#endif
- 
-     EGLint requestedDisplayType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
-     if (attrib_list)
-@@ -327,14 +329,16 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG
-         return EGL_NO_SURFACE;
-     }
- 
-+#if !defined(ANGLE_PLATFORM_WINRT)
-     HWND window = (HWND)win;
- 
-     if (!IsWindow(window))
-     {
-         return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
-     }
-+#endif
- 
--    return display->createWindowSurface(window, config, attrib_list);
-+    return display->createWindowSurface(win, config, attrib_list);
- }
- 
- EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
-diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp
-index 8a1baef..e74737e 100644
---- a/src/3rdparty/angle/src/libEGL/main.cpp
-+++ b/src/3rdparty/angle/src/libEGL/main.cpp
-@@ -11,6 +11,9 @@
- #include "common/debug.h"
- #include "common/tls.h"
- 
-+#if defined(ANGLE_PLATFORM_WINRT)
-+__declspec(thread)
-+#endif
- static TLSIndex currentTLS = TLS_OUT_OF_INDEXES;
  
- namespace egl
-@@ -18,6 +21,12 @@ namespace egl
- 
- Current *AllocateCurrent()
- {
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    if (currentTLS == TLS_OUT_OF_INDEXES)
-+    {
-+        currentTLS = CreateTLSIndex();
-+    }
-+#endif
-     ASSERT(currentTLS != TLS_OUT_OF_INDEXES);
-     if (currentTLS == TLS_OUT_OF_INDEXES)
-     {
-@@ -42,6 +51,12 @@ Current *AllocateCurrent()
- 
- void DeallocateCurrent()
- {
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    if (currentTLS == TLS_OUT_OF_INDEXES)
-+    {
-+        return;
-+    }
-+#endif
-     Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
-     SafeDelete(current);
-     SetTLSValue(currentTLS, NULL);
-@@ -72,6 +87,10 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
-             }
- #endif
- 
-+#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain
-+            return DisableThreadLibraryCalls(instance);
-+#endif
-+
-             currentTLS = CreateTLSIndex();
-             if (currentTLS == TLS_OUT_OF_INDEXES)
-             {
-@@ -86,7 +105,9 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
-         break;
-       case DLL_THREAD_DETACH:
-         {
-+#if !defined(ANGLE_PLATFORM_WINRT)
-             egl::DeallocateCurrent();
-+#endif
-         }
-         break;
-       case DLL_PROCESS_DETACH:
-diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp
-index 1c577bc..51447e2 100644
---- a/src/3rdparty/angle/src/libGLESv2/main.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/main.cpp
-@@ -11,6 +11,9 @@
- 
- #include "common/tls.h"
- 
-+#if defined(ANGLE_PLATFORM_WINRT)
-+__declspec(thread)
-+#endif
- static TLSIndex currentTLS = TLS_OUT_OF_INDEXES;
- 
- namespace gl
-@@ -18,6 +21,12 @@ namespace gl
- 
- Current *AllocateCurrent()
- {
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    if (currentTLS == TLS_OUT_OF_INDEXES)
-+    {
-+        currentTLS = CreateTLSIndex();
-+    }
-+#endif
-     ASSERT(currentTLS != TLS_OUT_OF_INDEXES);
-     if (currentTLS == TLS_OUT_OF_INDEXES)
-     {
-@@ -39,6 +48,12 @@ Current *AllocateCurrent()
- 
- void DeallocateCurrent()
- {
-+#if defined(ANGLE_PLATFORM_WINRT)
-+    if (currentTLS == TLS_OUT_OF_INDEXES)
++    switch (attribute)
 +    {
-+        return;
++    case EGL_WIDTH:
++        if (!eglSurface->isFixedSize() || !value) {
++            recordError(egl::Error(EGL_BAD_PARAMETER));
++            return EGL_FALSE;
++        }
++        eglSurface->setFixedWidth(value);
++        return EGL_TRUE;
++    case EGL_HEIGHT:
++        if (!eglSurface->isFixedSize() || !value) {
++            recordError(egl::Error(EGL_BAD_PARAMETER));
++            return EGL_FALSE;
++        }
++        eglSurface->setFixedHeight(value);
++        return EGL_TRUE;
++    default:
++        break;
 +    }
-+#endif
-     Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
-     SafeDelete(current);
-     SetTLSValue(currentTLS, NULL);
-@@ -54,6 +69,9 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
-     {
-       case DLL_PROCESS_ATTACH:
-         {
-+#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain
-+            return DisableThreadLibraryCalls(instance);
-+#endif
-             currentTLS = CreateTLSIndex();
-             if (currentTLS == TLS_OUT_OF_INDEXES)
-             {
-@@ -73,8 +91,10 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
-         break;
-       case DLL_PROCESS_DETACH:
-         {
-+#if !defined(ANGLE_PLATFORM_WINRT)
-             gl::DeallocateCurrent();
-             DestroyTLSIndex(currentTLS);
-+#endif
-         }
-         break;
-       default:
-diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h
-index 684c302..c30ad33 100644
---- a/src/3rdparty/angle/src/libGLESv2/main.h
-+++ b/src/3rdparty/angle/src/libGLESv2/main.h
-@@ -14,6 +14,10 @@
- #include <GLES2/gl2.h>
- #include <EGL/egl.h>
- 
-+#ifndef Sleep
-+#define Sleep(ms) WaitForSingleObjectEx(GetCurrentThread(), ms, FALSE)
-+#endif
 +
- namespace egl
- {
- class Display;
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
-index 7adbea2..b224974 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
-@@ -107,7 +107,7 @@ class Renderer
- 
-     virtual void sync(bool block) = 0;
- 
--    virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
-+    virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
- 
-     virtual gl::Error generateSwizzle(gl::Texture *texture) = 0;
-     virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0;
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
-index 12be9b3..1ec702f 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
-@@ -15,14 +15,23 @@
- 
- #include <GLES2/gl2.h>
- #include <EGL/egl.h>
-+#include <EGL/eglplatform.h>
+     UNIMPLEMENTED();   // FIXME
  
- namespace rx
- {
- 
-+enum SwapFlags
-+{
-+    SWAP_NORMAL = 0,
-+    SWAP_ROTATE_90 = 1,
-+    SWAP_ROTATE_270 = 2,
-+    SWAP_ROTATE_180 = SWAP_ROTATE_90|SWAP_ROTATE_270,
-+};
-+
- class SwapChain
- {
-   public:
--    SwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
-+    SwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
-         : mWindow(window), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat)
-     {
-     }
-@@ -31,13 +40,13 @@ class SwapChain
- 
-     virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0;
-     virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0;
--    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
-+    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags) = 0;
-     virtual void recreate() = 0;
- 
-     virtual HANDLE getShareHandle() {return mShareHandle;};
- 
-   protected:
--    const HWND mWindow;            // Window that the surface is created for.
-+    const EGLNativeWindowType mWindow;            // Window that the surface is created for.
-     const GLenum mBackBufferFormat;
-     const GLenum mDepthBufferFormat;
- 
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-index 5715d5f..d013197 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-@@ -9,6 +9,7 @@
- #include "libGLESv2/main.h"
- 
- #include "common/utilities.h"
-+#include "common/platform.h"
- 
- #if defined(__MINGW32__) && !defined(D3DCOMPILER_DLL)
- 
-@@ -45,11 +46,7 @@ HLSLCompiler::~HLSLCompiler()
- 
- bool HLSLCompiler::initialize()
- {
--<<<<<<< HEAD
--    TRACE_EVENT0("gpu", "initializeCompiler");
--=======
- #if !defined(ANGLE_PLATFORM_WINRT)
-->>>>>>> 429814a... ANGLE: remove event tracing
- #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
-     // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
-     static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
-@@ -94,7 +91,9 @@ bool HLSLCompiler::initialize()
- 
-     mD3DCompileFunc = reinterpret_cast<CompileFuncPtr>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
-     ASSERT(mD3DCompileFunc);
--
-+#else
-+    mD3DCompileFunc = reinterpret_cast<CompileFuncPtr>(&D3DCompile);
-+#endif
-     return mD3DCompileFunc != NULL;
- }
- 
-@@ -111,7 +110,9 @@ void HLSLCompiler::release()
- ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile,
-                                           const UINT optimizationFlags[], const char *flagNames[], int attempts) const
- {
-+#if !defined(ANGLE_PLATFORM_WINRT)
-     ASSERT(mD3DCompilerModule && mD3DCompileFunc);
-+#endif
- 
-     if (!hlsl)
-     {
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-index ed880c3..0bb7489 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-@@ -6,6 +6,7 @@
- 
- // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
- 
-+#include "common/platform.h"
- #include "libGLESv2/main.h"
- #include "libGLESv2/Buffer.h"
- #include "libGLESv2/FramebufferAttachment.h"
-@@ -135,6 +136,7 @@ EGLint Renderer11::initialize()
-         return EGL_NOT_INITIALIZED;
-     }
- 
-+#if !defined(ANGLE_PLATFORM_WINRT)
-     mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
-     mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
- 
-@@ -153,6 +155,7 @@ EGLint Renderer11::initialize()
-         ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
-         return EGL_NOT_INITIALIZED;
-     }
-+#endif
- 
-     D3D_FEATURE_LEVEL featureLevels[] =
-     {
-@@ -207,7 +210,7 @@ EGLint Renderer11::initialize()
-         }
-     }
- 
--#if !ANGLE_SKIP_DXGI_1_2_CHECK
-+#if !ANGLE_SKIP_DXGI_1_2_CHECK && !defined(ANGLE_PLATFORM_WINRT)
-     // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required.
-     // The easiest way to check is to query for a IDXGIDevice2.
-     bool requireDXGI1_2 = false;
-@@ -237,8 +240,12 @@ EGLint Renderer11::initialize()
-     }
- #endif
- 
-+#if !defined(ANGLE_PLATFORM_WINRT)
-     IDXGIDevice *dxgiDevice = NULL;
--    result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
-+#else
-+    IDXGIDevice1 *dxgiDevice = NULL;
-+#endif
-+    result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice));
- 
-     if (FAILED(result))
-     {
-@@ -408,7 +415,7 @@ void Renderer11::sync(bool block)
-     }
- }
- 
--SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
-+SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
- {
-     return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat);
- }
+     recordError(egl::Error(EGL_SUCCESS));
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
-index d309f14..b86f5e5 100644
+index 1655f1d..c789cae 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
-@@ -57,7 +57,7 @@ class Renderer11 : public Renderer
- 
-     virtual void sync(bool block);
- 
--    virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
-+    virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
- 
-     virtual gl::Error generateSwizzle(gl::Texture *texture);
-     virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
-@@ -222,7 +222,7 @@ class Renderer11 : public Renderer
+@@ -231,7 +231,7 @@ class Renderer11 : public RendererD3D
  
      HMODULE mD3d11Module;
      HMODULE mDxgiModule;
 -    HDC mDc;
 +    EGLNativeDisplayType mDc;
-     EGLint mRequestedDisplay;
+     std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
+     D3D_DRIVER_TYPE mDriverType;
  
-     HLSLCompiler mCompiler;
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
-index 50dae4e..787c511 100644
+index 834b7bd..52c8a81 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
-@@ -6,6 +6,7 @@
- 
- // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain.
- 
-+#include "common/platform.h"
- #include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
- #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
- #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
-@@ -18,7 +19,7 @@
- namespace rx
- {
- 
--SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle,
-+SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
-                          GLenum backBufferFormat, GLenum depthBufferFormat)
-     : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
- {
-@@ -38,6 +39,8 @@ SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle,
+@@ -42,6 +42,8 @@ SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE
      mPassThroughPS = NULL;
      mWidth = -1;
      mHeight = -1;
-+    mViewportWidth = -1;
-+    mViewportHeight = -1;
++    mRotateL = false;
++    mRotateR = false;
      mSwapInterval = 0;
      mAppCreatedShareHandle = mShareHandle != NULL;
      mPassThroughResourcesInit = false;
-@@ -92,6 +95,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
-     ASSERT(backbufferHeight >= 1);
+@@ -92,10 +94,11 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
+     ASSERT(device != NULL);
+ 
+     // D3D11 does not allow zero size textures
+-    ASSERT(backbufferWidth >= 1);
+-    ASSERT(backbufferHeight >= 1);
++    ASSERT(backbufferWidth != 0);
++    ASSERT(backbufferHeight != 0);
  
      // Preserve the render target content
-+#if !defined(ANGLE_PLATFORM_WINRT)
++#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
      ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
      if (previousOffscreenTexture)
      {
-@@ -99,6 +103,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
+@@ -103,6 +106,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
      }
      const int previousWidth = mWidth;
      const int previousHeight = mHeight;
@@ -1128,112 +675,107 @@ index 50dae4e..787c511 100644
  
      releaseOffscreenTexture();
  
-@@ -281,7 +286,12 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
- 
+@@ -136,8 +140,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
+         D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
+         mOffscreenTexture->GetDesc(&offscreenTextureDesc);
+ 
+-        if (offscreenTextureDesc.Width != (UINT)backbufferWidth ||
+-            offscreenTextureDesc.Height != (UINT)backbufferHeight ||
++        if (offscreenTextureDesc.Width != UINT(abs(backbufferWidth)) ||
++            offscreenTextureDesc.Height != UINT(abs(backbufferHeight)) ||
+             offscreenTextureDesc.Format != backbufferFormatInfo.texFormat ||
+             offscreenTextureDesc.MipLevels != 1 ||
+             offscreenTextureDesc.ArraySize != 1)
+@@ -152,8 +156,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
+         const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport();
+ 
+         D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
+-        offscreenTextureDesc.Width = backbufferWidth;
+-        offscreenTextureDesc.Height = backbufferHeight;
++        offscreenTextureDesc.Width = abs(backbufferWidth);
++        offscreenTextureDesc.Height = abs(backbufferHeight);
+         offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
+         offscreenTextureDesc.MipLevels = 1;
+         offscreenTextureDesc.ArraySize = 1;
+@@ -233,8 +237,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
+     if (mDepthBufferFormat != GL_NONE)
+     {
+         D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
+-        depthStencilTextureDesc.Width = backbufferWidth;
+-        depthStencilTextureDesc.Height = backbufferHeight;
++        depthStencilTextureDesc.Width = abs(backbufferWidth);
++        depthStencilTextureDesc.Height = abs(backbufferHeight);
+         depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat;
+         depthStencilTextureDesc.MipLevels = 1;
+         depthStencilTextureDesc.ArraySize = 1;
+@@ -286,6 +290,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
      mWidth = backbufferWidth;
      mHeight = backbufferHeight;
-+#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP
-+    mViewportWidth = backbufferWidth;
-+    mViewportHeight = backbufferHeight;
-+#endif
  
-+#if !defined(ANGLE_PLATFORM_WINRT)
++#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
      if (previousOffscreenTexture != NULL)
      {
          D3D11_BOX sourceBox = {0};
-@@ -300,9 +310,10 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
- 
-         if (mSwapChain)
-         {
--            swapRect(0, 0, mWidth, mHeight);
-+            swapRect(0, 0, mWidth, mHeight, SWAP_NORMAL);
+@@ -307,6 +312,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
+             swapRect(0, 0, mWidth, mHeight);
          }
      }
 +#endif
  
      return EGL_SUCCESS;
  }
-@@ -329,8 +340,15 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
-     SafeRelease(mBackBufferRTView);
+@@ -320,8 +326,16 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
+         return EGL_BAD_ACCESS;
+     }
  
-     // Resize swap chain
-+    HRESULT result;
-+#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP // Windows phone swap chain is never resized, only the texture is
-+#if !defined(ANGLE_PLATFORM_WINRT)
-+    const int bufferCount = 1;
-+#else
-+    const int bufferCount = 2;
++    // Windows Phone works around the rotation limitation by using negative values for the swap chain size
++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
++    mRotateL = backbufferWidth < 0; // Landscape/InvertedLandscape
++    mRotateR = backbufferHeight < 0; // InvertedPortrait/InvertedLandscape
++    backbufferWidth = abs(backbufferWidth);
++    backbufferHeight = abs(backbufferHeight);
 +#endif
-     const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat);
--    HRESULT result = mSwapChain->ResizeBuffers(1, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0);
-+    result = mSwapChain->ResizeBuffers(bufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0);
- 
-     if (FAILED(result))
++
+     // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
+-    if (backbufferWidth < 1 || backbufferHeight < 1)
++    if (backbufferWidth == 0 || backbufferHeight == 0)
      {
-@@ -346,6 +364,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
-             return EGL_BAD_ALLOC;
-         }
+         return EGL_SUCCESS;
      }
-+#endif
- 
-     result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
-     ASSERT(SUCCEEDED(result));
-@@ -399,6 +418,7 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
+@@ -329,6 +343,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
+     // Can only call resize if we have already created our swap buffer and resources
+     ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
  
-         IDXGIFactory *factory = mRenderer->getDxgiFactory();
- 
-+#if !defined(ANGLE_PLATFORM_WINRT)
-         DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
-         swapChainDesc.BufferDesc.Width = backbufferWidth;
-         swapChainDesc.BufferDesc.Height = backbufferHeight;
-@@ -417,7 +437,37 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
-         swapChainDesc.Flags = 0;
++#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // The swap chain is not directly resized on Windows Phone
+     SafeRelease(mBackBufferTexture);
+     SafeRelease(mBackBufferRTView);
  
-         HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
-+#else
-+        IDXGIFactory2 *factory2;
-+        HRESULT result = factory->QueryInterface(IID_PPV_ARGS(&factory2));
-+        ASSERT(SUCCEEDED(result));
-+
-+        DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
-+        swapChainDesc.Width = 0;
-+        swapChainDesc.Height = 0;
-+        swapChainDesc.Format = backbufferFormatInfo.texFormat;
-+        swapChainDesc.SampleDesc.Count = 1;
-+        swapChainDesc.SampleDesc.Quality = 0;
-+        swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-+        swapChainDesc.Stereo = FALSE;
-+        swapChainDesc.Flags = 0;
-+#if WINAPI_FAMILY==WINAPI_FAMILY_PC_APP
-+        swapChainDesc.Scaling = DXGI_SCALING_NONE;
-+        swapChainDesc.BufferCount = 2;
-+        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
-+#elif WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-+        swapChainDesc.BufferCount = 1;
-+        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+@@ -366,6 +381,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
+     {
+         d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
+     }
 +#endif
  
-+        IDXGISwapChain1 *swapChain;
-+        result = factory2->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain);
-+        mSwapChain = swapChain;
-+        HRESULT hr = swapChain->GetDesc1(&swapChainDesc);
-+        ASSERT(SUCCEEDED(hr));
-+        mViewportWidth = swapChainDesc.Width;
-+        mViewportHeight = swapChainDesc.Height;
-+#endif
-         if (FAILED(result))
-         {
-             ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
-@@ -513,7 +563,7 @@ void SwapChain11::initPassThroughResources()
+     return resetOffscreenTexture(backbufferWidth, backbufferHeight);
  }
- 
- // parameters should be validated/clamped by caller
--EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
-+EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags)
- {
-     if (!mSwapChain)
-     {
-@@ -544,10 +594,13 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+@@ -512,16 +528,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+     ID3D11Device *device = mRenderer->getDevice();
+     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ 
+-    // Set vertices
+-    D3D11_MAPPED_SUBRESOURCE mappedResource;
+-    HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+-    if (FAILED(result))
+-    {
+-        return EGL_BAD_ACCESS;
+-    }
+-
+-    d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
+-
+     // Create a quad in homogeneous coordinates
+     float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
+     float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
+@@ -533,10 +539,23 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
      float u2 = (x + width) / float(mWidth);
      float v2 = (y + height) / float(mHeight);
  
@@ -1241,8 +783,18 @@ index 50dae4e..787c511 100644
 -    d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
 -    d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
 -    d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
-+    const int rotateL = flags & SWAP_ROTATE_90;
-+    const int rotateR = flags & SWAP_ROTATE_270;
++    const bool rotateL = mRotateL;
++    const bool rotateR = mRotateR;
++
++    // Set vertices
++    D3D11_MAPPED_SUBRESOURCE mappedResource;
++    HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
++    if (FAILED(result))
++    {
++        return EGL_BAD_ACCESS;
++    }
++
++    d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
 +
 +    d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1);
 +    d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2);
@@ -1251,72 +803,35 @@ index 50dae4e..787c511 100644
  
      deviceContext->Unmap(mQuadVB, 0);
  
-@@ -577,8 +630,8 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+@@ -564,10 +583,11 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+ 
+     // Set the viewport
      D3D11_VIEWPORT viewport;
-     viewport.TopLeftX = 0;
-     viewport.TopLeftY = 0;
+-    viewport.TopLeftX = 0;
+-    viewport.TopLeftY = 0;
 -    viewport.Width = mWidth;
 -    viewport.Height = mHeight;
-+    viewport.Width = mViewportWidth;
-+    viewport.Height = mViewportHeight;
++    viewport.TopLeftX = 0.0f;
++    viewport.TopLeftY = 0.0f;
++    const bool invertViewport = (mRotateL || mRotateR) && !(mRotateL && mRotateR);
++    viewport.Width = FLOAT(invertViewport ? mHeight : mWidth);
++    viewport.Height = FLOAT(invertViewport ? mWidth : mHeight);
      viewport.MinDepth = 0.0f;
      viewport.MaxDepth = 1.0f;
      deviceContext->RSSetViewports(1, &viewport);
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h
-index fb0afd7..b30b785 100644
+index 22401d8..77509ed 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h
-@@ -19,13 +19,13 @@ class Renderer11;
- class SwapChain11 : public SwapChain
- {
-   public:
--    SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle,
-+    SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle,
-                 GLenum backBufferFormat, GLenum depthBufferFormat);
-     virtual ~SwapChain11();
- 
-     EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
-     virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
--    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
-+    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags);
-     virtual void recreate();
- 
-     virtual ID3D11Texture2D *getOffscreenTexture();
 @@ -52,6 +52,8 @@ class SwapChain11 : public SwapChain
      Renderer11 *mRenderer;
      EGLint mHeight;
      EGLint mWidth;
-+    EGLint mViewportWidth;
-+    EGLint mViewportHeight;
++    bool mRotateL;
++    bool mRotateR;
      bool mAppCreatedShareHandle;
      unsigned int mSwapInterval;
      bool mPassThroughResourcesInit;
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp
-index f702b79..0aeaabb 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp
-@@ -238,7 +238,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
- }
- 
- // parameters should be validated/clamped by caller
--EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
-+EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint)
- {
-     if (!mSwapChain)
-     {
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h
-index 16a62bd..4d756f8 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h
-@@ -25,7 +25,7 @@ class SwapChain9 : public SwapChain
- 
-     EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
-     virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
--    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
-+    virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint);
-     virtual void recreate();
- 
-     virtual IDirect3DSurface9 *getRenderTarget();
 -- 
-1.9.0.msysgit.0
+1.9.4.msysgit.1
 
diff --git a/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch b/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch
index 297d5adc841..dd2768cf3ed 100644
--- a/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch
+++ b/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch
@@ -1,6 +1,6 @@
-From 0e8aa60332e17f284804dc1b89a9db5795a92ecb Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@digia.com>
-Date: Wed, 17 Sep 2014 21:17:39 +0300
+From 829bf86c57357d3c8ec598b92fcfdb1849e84075 Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@theqtcompany.com>
+Date: Tue, 11 Nov 2014 17:11:54 +0200
 Subject: [PATCH 10/16] ANGLE: Enable D3D11 for feature level 9 cards
 
 Enable use of ANGLE on lower-end hardware, such as Surface RT and
@@ -8,23 +8,32 @@ Windows Phone 8.
 
 Change-Id: Ice536802e4eedc1d264abd0dd65960638fce59e4
 ---
- src/3rdparty/angle/src/libGLESv2/angletypes.cpp    |   4 +-
- .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp    |  73 +++----
+ src/3rdparty/angle/src/libGLESv2/angletypes.cpp    |   6 +-
+ .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp    |  69 ++++---
  .../src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp  |   4 +-
- .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp   |   8 +-
- .../renderer/d3d/d3d11/PixelTransfer11.cpp         |   7 +-
- .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp    | 209 +++++++++++++--------
+ .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp   |   7 +-
+ .../renderer/d3d/d3d11/PixelTransfer11.cpp         |   9 +-
+ .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp    | 226 +++++++++++++--------
  .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h  |   1 +
- .../renderer/d3d/d3d11/TextureStorage11.cpp        |   2 +-
+ .../renderer/d3d/d3d11/TextureStorage11.cpp        |   4 +-
  .../libGLESv2/renderer/d3d/d3d11/formatutils11.cpp |   4 +-
  .../renderer/d3d/d3d11/renderer11_utils.cpp        |   2 +-
- 10 files changed, 190 insertions(+), 124 deletions(-)
+ 10 files changed, 208 insertions(+), 124 deletions(-)
 
 diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp
-index 06618d5..bb6425d 100644
+index 6fd02e0..5a0cfc5 100644
 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp
-@@ -22,8 +22,8 @@ SamplerState::SamplerState()
+@@ -12,6 +12,8 @@
+ #include "libGLESv2/State.h"
+ #include "libGLESv2/VertexArray.h"
+ 
++#include <float.h>
++
+ namespace gl
+ {
+ 
+@@ -24,8 +26,8 @@ SamplerState::SamplerState()
        maxAnisotropy(1.0f),
        baseLevel(0),
        maxLevel(1000),
@@ -36,28 +45,28 @@ index 06618d5..bb6425d 100644
        compareFunc(GL_LEQUAL),
        swizzleRed(GL_RED),
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
-index 72820a4..d43e65e 100644
+index 91e7552..06aea9b 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
-@@ -209,7 +209,7 @@ Blit11::Blit11(rx::Renderer11 *renderer)
+@@ -209,7 +209,7 @@ Blit11::Blit11(Renderer11 *renderer)
      pointSamplerDesc.BorderColor[2] = 0.0f;
      pointSamplerDesc.BorderColor[3] = 0.0f;
      pointSamplerDesc.MinLOD = 0.0f;
 -    pointSamplerDesc.MaxLOD = 0.0f;
-+    pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? FLT_MAX : 0.0f;
++    pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f;
  
      result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler);
      ASSERT(SUCCEEDED(result));
-@@ -228,7 +228,7 @@ Blit11::Blit11(rx::Renderer11 *renderer)
+@@ -228,7 +228,7 @@ Blit11::Blit11(Renderer11 *renderer)
      linearSamplerDesc.BorderColor[2] = 0.0f;
      linearSamplerDesc.BorderColor[3] = 0.0f;
      linearSamplerDesc.MinLOD = 0.0f;
 -    linearSamplerDesc.MaxLOD = 0.0f;
-+    linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? FLT_MAX : 0.0f;
++    linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f;
  
      result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler);
      ASSERT(SUCCEEDED(result));
-@@ -290,28 +290,31 @@ Blit11::Blit11(rx::Renderer11 *renderer)
+@@ -290,28 +290,31 @@ Blit11::Blit11(Renderer11 *renderer)
      ASSERT(SUCCEEDED(result));
      d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader");
  
@@ -76,14 +85,14 @@ index 72820a4..d43e65e 100644
 -    result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL);
 -    ASSERT(SUCCEEDED(result));
 -    d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout");
+-
+-    result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS);
+-    ASSERT(SUCCEEDED(result));
+-    d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader");
 +        result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS);
 +        ASSERT(SUCCEEDED(result));
 +        d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader");
  
--    result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS);
--    ASSERT(SUCCEEDED(result));
--    d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader");
--
 -    result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS);
 -    ASSERT(SUCCEEDED(result));
 -    d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader");
@@ -109,7 +118,7 @@ index 72820a4..d43e65e 100644
  
      buildShaderMap();
  
-@@ -972,40 +975,44 @@ void Blit11::buildShaderMap()
+@@ -970,22 +973,27 @@ void Blit11::buildShaderMap()
      ID3D11Device *device = mRenderer->getDevice();
  
      add2DBlitShaderToMap(GL_RGBA,            false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D,     "Blit11 2D RGBA pixel shader"           ));
@@ -145,19 +154,7 @@ index 72820a4..d43e65e 100644
      add3DBlitShaderToMap(GL_RGBA,            false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D,     "Blit11 3D RGBA pixel shader"           ));
      add3DBlitShaderToMap(GL_RGBA_INTEGER,    false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI,   "Blit11 3D UI RGBA pixel shader"        ));
      add3DBlitShaderToMap(GL_RGBA_INTEGER,    true,  d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI,    "Blit11 3D I RGBA pixel shader"         ));
-     add3DBlitShaderToMap(GL_BGRA_EXT,        false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D,     "Blit11 3D BGRA pixel shader"           ));
-     add3DBlitShaderToMap(GL_RGB,             false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D,      "Blit11 3D RGB pixel shader"            ));
-+    add3DBlitShaderToMap(GL_RG,              false, d3d11::CompilePS(device, g_PS_PassthroughRG3D,       "Blit11 3D RG pixel shader"             ));
-     add3DBlitShaderToMap(GL_RGB_INTEGER,     false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI,    "Blit11 3D RGB UI pixel shader"         ));
-     add3DBlitShaderToMap(GL_RGB_INTEGER,     true,  d3d11::CompilePS(device, g_PS_PassthroughRGB3DI,     "Blit11 3D RGB I pixel shader"          ));
--    add3DBlitShaderToMap(GL_RG,              false, d3d11::CompilePS(device, g_PS_PassthroughRG3D,       "Blit11 3D RG pixel shader"             ));
-+    add3DBlitShaderToMap(GL_RED,             false, d3d11::CompilePS(device, g_PS_PassthroughR3D,        "Blit11 3D R pixel shader"              ));
-     add3DBlitShaderToMap(GL_RG_INTEGER,      false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI,     "Blit11 3D RG UI pixel shader"          ));
-     add3DBlitShaderToMap(GL_RG_INTEGER,      true,  d3d11::CompilePS(device, g_PS_PassthroughRG3DI,      "Blit11 3D RG I pixel shader"           ));
--    add3DBlitShaderToMap(GL_RED,             false, d3d11::CompilePS(device, g_PS_PassthroughR3D,        "Blit11 3D R pixel shader"              ));
-     add3DBlitShaderToMap(GL_RED_INTEGER,     false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI,      "Blit11 3D R UI pixel shader"           ));
-     add3DBlitShaderToMap(GL_RED_INTEGER,     true,  d3d11::CompilePS(device, g_PS_PassthroughR3DI,       "Blit11 3D R I pixel shader"            ));
-     add3DBlitShaderToMap(GL_ALPHA,           false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D,     "Blit11 3D alpha pixel shader"          ));
+@@ -1003,7 +1011,6 @@ void Blit11::buildShaderMap()
      add3DBlitShaderToMap(GL_LUMINANCE,       false, d3d11::CompilePS(device, g_PS_PassthroughLum3D,      "Blit11 3D luminance pixel shader"      ));
      add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader"));
  
@@ -166,22 +163,22 @@ index 72820a4..d43e65e 100644
      addSwizzleShaderToMap(GL_INT,          D3D_SRV_DIMENSION_TEXTURE2D,      d3d11::CompilePS(device, g_PS_SwizzleI2D,       "Blit11 2D I swizzle pixel shader" ));
  
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
-index 43ce5ba..ecd4d46 100644
+index 2d5fa3c..5aab379 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
-@@ -747,7 +747,9 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren
+@@ -753,7 +753,9 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren
  
        case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
          bufferDesc->Usage = D3D11_USAGE_DEFAULT;
 -        bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_STREAM_OUTPUT;
 +        bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER;
-+        if (!static_cast<Renderer11 *>(renderer)->isLevel9())
++        if (!renderer->isLevel9())
 +            bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT;
          bufferDesc->CPUAccessFlags = 0;
          break;
  
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
-index 5caa427..765d34f 100644
+index 4630762..7185a05 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
 @@ -104,7 +104,7 @@ Clear11::Clear11(Renderer11 *renderer)
@@ -189,11 +186,11 @@ index 5caa427..765d34f 100644
      rsDesc.DepthBiasClamp = 0.0f;
      rsDesc.SlopeScaledDepthBias = 0.0f;
 -    rsDesc.DepthClipEnable = FALSE;
-+    rsDesc.DepthClipEnable = mRenderer->isLevel9();
++    rsDesc.DepthClipEnable = renderer->isLevel9();
      rsDesc.ScissorEnable = FALSE;
      rsDesc.MultisampleEnable = FALSE;
      rsDesc.AntialiasedLineEnable = FALSE;
-@@ -114,6 +114,12 @@ Clear11::Clear11(Renderer11 *renderer)
+@@ -114,6 +114,11 @@ Clear11::Clear11(Renderer11 *renderer)
      d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state");
  
      mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat);
@@ -202,53 +199,63 @@ index 5caa427..765d34f 100644
 +        memset(&mIntClearShader, 0, sizeof(ClearShader));
 +        return;
 +    }
-+
      mUintClearShader  = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT,  g_VS_ClearUint,  g_PS_ClearUint );
      mIntClearShader   = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT,  g_VS_ClearSint,  g_PS_ClearSint );
  }
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
-index edaafec..a4e84f9 100644
+index a4072d8..6a3d347 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
-@@ -88,13 +88,16 @@ PixelTransfer11::PixelTransfer11(Renderer11 *renderer)
-     ASSERT(SUCCEEDED(result));
-     d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer");
- 
-+    StructZero(&mParamsData);
-+
-     // init shaders
-+    if (mRenderer->isLevel9())
-+        return;
-+
-     mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS");
-     mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
+@@ -133,10 +133,13 @@ gl::Error PixelTransfer11::loadResources()
+         return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader.");
+     }
  
-     buildShaderMap();
--
--    StructZero(&mParamsData);
- }
+-    mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
+-    if (!mBufferToTextureGS)
++    if (!mRenderer->isLevel9())
+     {
+-        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader.");
++        mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
++        if (!mBufferToTextureGS)
++        {
++            return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader.");
++        }
+     }
  
- PixelTransfer11::~PixelTransfer11()
+     gl::Error error = buildShaderMap();
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-index 0bb7489..b4b26a8 100644
+index ffc6cc9..f6ba930 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-@@ -162,6 +162,11 @@ EGLint Renderer11::initialize()
-         D3D_FEATURE_LEVEL_11_0,
-         D3D_FEATURE_LEVEL_10_1,
-         D3D_FEATURE_LEVEL_10_0,
+@@ -153,6 +153,24 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const eg
+         }
+     }
+ 
 +#if !defined(ANGLE_ENABLE_D3D9)
-+        D3D_FEATURE_LEVEL_9_3,
-+        D3D_FEATURE_LEVEL_9_2,
-+        D3D_FEATURE_LEVEL_9_1,
++    if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9)
++    {
++        if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3)
++        {
++            mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
++        }
++        if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2)
++        {
++            mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2);
++        }
++        if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
++        {
++            mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1);
++        }
++    }
 +#endif
-     };
- 
-     D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE;
-@@ -1112,6 +1117,84 @@ gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, cons
++
+     mDriverType = (attributes.get(EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_FALSE) == EGL_TRUE) ? D3D_DRIVER_TYPE_WARP
+                                                                                              : D3D_DRIVER_TYPE_HARDWARE;
+ }
+@@ -1170,6 +1188,83 @@ gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, cons
+         return gl::Error(GL_NO_ERROR);
      }
  }
- 
 +template<typename T>
 +static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data)
 +{
@@ -326,12 +333,11 @@ index 0bb7489..b4b26a8 100644
 +      default: UNREACHABLE();
 +    }
 +}
-+
+ 
  gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
  {
-     // Get the raw indices for an indexed draw
-@@ -1123,10 +1206,13 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
-         indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+@@ -1189,10 +1284,13 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
+         indices = bufferData + offset;
      }
  
 +    // TODO: some level 9 hardware supports 32-bit indices; test and store support instead
@@ -345,7 +351,7 @@ index 0bb7489..b4b26a8 100644
          if (error.isError())
          {
              SafeDelete(mLineLoopIB);
-@@ -1137,7 +1223,8 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
+@@ -1203,7 +1301,8 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
      // Checked by Renderer11::applyPrimitiveType
      ASSERT(count >= 0);
  
@@ -355,7 +361,7 @@ index 0bb7489..b4b26a8 100644
      {
          return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
      }
-@@ -1157,42 +1244,12 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
+@@ -1223,42 +1322,12 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
          return error;
      }
  
@@ -402,8 +408,8 @@ index 0bb7489..b4b26a8 100644
      error = mLineLoopIB->unmapBuffer();
      if (error.isError())
      {
-@@ -1227,10 +1284,12 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
-         indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+@@ -1300,10 +1369,12 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
+         indices = bufferData + offset;
      }
  
 +    const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
@@ -416,7 +422,7 @@ index 0bb7489..b4b26a8 100644
          if (error.isError())
          {
              SafeDelete(mTriangleFanIB);
-@@ -1243,13 +1302,14 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
+@@ -1316,13 +1387,14 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
  
      const unsigned int numTris = count - 2;
  
@@ -434,7 +440,7 @@ index 0bb7489..b4b26a8 100644
      if (error.isError())
      {
          return error;
-@@ -1263,45 +1323,12 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
+@@ -1336,45 +1408,12 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
          return error;
      }
  
@@ -485,7 +491,7 @@ index 0bb7489..b4b26a8 100644
  
      error = mTriangleFanIB->unmapBuffer();
      if (error.isError())
-@@ -1549,7 +1576,7 @@ gl::Error Renderer11::applyUniforms(const gl::ProgramBinary &programBinary)
+@@ -1634,7 +1673,7 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto
      }
  
      // needed for the point sprite geometry shader
@@ -494,19 +500,7 @@ index 0bb7489..b4b26a8 100644
      {
          mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
          mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
-@@ -1711,6 +1738,11 @@ bool Renderer11::testDeviceResettable()
-         D3D_FEATURE_LEVEL_11_0,
-         D3D_FEATURE_LEVEL_10_1,
-         D3D_FEATURE_LEVEL_10_0,
-+#if !defined(ANGLE_ENABLE_D3D9)
-+        D3D_FEATURE_LEVEL_9_3,
-+        D3D_FEATURE_LEVEL_9_2,
-+        D3D_FEATURE_LEVEL_9_1,
-+#endif
-     };
- 
-     ID3D11Device* dummyDevice;
-@@ -1862,7 +1894,10 @@ int Renderer11::getMajorShaderModel() const
+@@ -1938,7 +1977,10 @@ int Renderer11::getMajorShaderModel() const
      {
        case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION;   // 5
        case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4
@@ -518,7 +512,7 @@ index 0bb7489..b4b26a8 100644
        default: UNREACHABLE();      return 0;
      }
  }
-@@ -1873,7 +1908,10 @@ int Renderer11::getMinorShaderModel() const
+@@ -1949,7 +1991,10 @@ int Renderer11::getMinorShaderModel() const
      {
        case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION;   // 0
        case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1
@@ -530,49 +524,81 @@ index 0bb7489..b4b26a8 100644
        default: UNREACHABLE();      return 0;
      }
  }
-@@ -2387,6 +2425,15 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch
-       case D3D_FEATURE_LEVEL_10_0:
-         profileVersion = "4_0";
+@@ -2455,6 +2500,7 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin
+ 
+     unsigned int profileMajorVersion = 0;
+     unsigned int profileMinorVersion = 0;
++    const char *profileSuffix = NULL;
+     switch (mFeatureLevel)
+     {
+       case D3D_FEATURE_LEVEL_11_0:
+@@ -2469,12 +2515,30 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin
+         profileMajorVersion = 4;
+         profileMinorVersion = 0;
          break;
 +      case D3D_FEATURE_LEVEL_9_3:
-+        profileVersion = "4_0_level_9_3";
++        profileMajorVersion = 4;
++        profileMinorVersion = 0;
++        profileSuffix = "_level_9_3";
 +        break;
 +      case D3D_FEATURE_LEVEL_9_2:
-+        profileVersion = "4_0_level_9_2";
++        profileMajorVersion = 4;
++        profileMinorVersion = 0;
++        profileSuffix = "_level_9_2";
 +        break;
 +      case D3D_FEATURE_LEVEL_9_1:
-+        profileVersion = "4_0_level_9_1";
++        profileMajorVersion = 4;
++        profileMinorVersion = 0;
++        profileSuffix = "_level_9_1";
 +        break;
++      break;
        default:
          UNREACHABLE();
-         return NULL;
+         return gl::Error(GL_INVALID_OPERATION);
+     }
+ 
+     std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
++    if (profileSuffix)
++        profile += profileSuffix;
+ 
+     UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;
+ 
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
-index b86f5e5..2a53fa1 100644
+index c789cae..d44bd2f 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
-@@ -184,6 +184,7 @@ class Renderer11 : public Renderer
+@@ -188,6 +188,7 @@ class Renderer11 : public RendererD3D
      ID3D11Device *getDevice() { return mDevice; }
      ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
-     IDXGIFactory *getDxgiFactory() { return mDxgiFactory; };
+     DXGIFactory *getDxgiFactory() { return mDxgiFactory; };
 +    bool isLevel9() { return mFeatureLevel <= D3D_FEATURE_LEVEL_9_3; }
  
      Blit11 *getBlitter() { return mBlit; }
  
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
-index 3f0cd5b..91e7147 100644
+index 4287918..74af27e 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
-@@ -472,7 +472,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform
+@@ -744,7 +744,7 @@ gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource)
          D3D11_TEXTURE2D_DESC desc;
-         desc.Width = width;      // Compressed texture size constraints?
-         desc.Height = height;
--        desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
-+        desc.MipLevels = desc.MipLevels = mRenderer->isLevel9() ? 1 : ((levels > 0) ? (mTopLevel + levels) : 0);
+         desc.Width = mTextureWidth;      // Compressed texture size constraints?
+         desc.Height = mTextureHeight;
+-        desc.MipLevels = mMipLevels;
++        desc.MipLevels = mRenderer->isLevel9() ? 1 : mMipLevels;
          desc.ArraySize = 1;
          desc.Format = mTextureFormat;
          desc.SampleDesc.Count = 1;
+@@ -863,7 +863,7 @@ gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORM
+     srvDesc.Format = format;
+     srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+     srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
+-    srvDesc.Texture2D.MipLevels = mipLevels;
++    srvDesc.Texture2D.MipLevels = mRenderer->isLevel9() ? -1 : mipLevels;
+ 
+     ID3D11Device *device = mRenderer->getDevice();
+     HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
-index 1ea916d..c078287 100644
+index 1ea916d..90a879e 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
 @@ -557,7 +557,7 @@ D3D11LoadFunctionMap BuildD3D11LoadFunctionMap()
@@ -589,15 +615,15 @@ index 1ea916d..c078287 100644
      // From GL_EXT_texture_storage
      //                           | GL internal format     | D3D11 texture format          | D3D11 SRV format                    | D3D11 RTV format              | D3D11 DSV format               |
 -    InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT,             DXGI_FORMAT_A8_UNORM,           DXGI_FORMAT_A8_UNORM,                 DXGI_FORMAT_A8_UNORM,           DXGI_FORMAT_UNKNOWN           );
-+    InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT,             DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_UNKNOWN           );
++    InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT,             DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_UNKNOWN           );
      InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT,         DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_R8G8B8A8_UNORM,           DXGI_FORMAT_R8G8B8A8_UNORM,     DXGI_FORMAT_UNKNOWN           );
      InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT,           DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT,       DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN           );
      InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT,       DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT,       DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN           );
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-index b1867fb..06a22eb 100644
+index 9ffc32e..cbfe557 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-@@ -283,7 +283,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
+@@ -284,7 +284,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
          // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
        case D3D_FEATURE_LEVEL_9_3:
        case D3D_FEATURE_LEVEL_9_2:
@@ -607,5 +633,5 @@ index b1867fb..06a22eb 100644
        default: UNREACHABLE();      return false;
      }
 -- 
-1.9.0.msysgit.0
+1.9.4.msysgit.1
 
diff --git a/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch b/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch
index 35d525fb2d6..afc9f256a1e 100644
--- a/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch
+++ b/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch
@@ -1,6 +1,6 @@
-From 9e167b788cc9de1d963fd3fc2145848a6ccc0fa8 Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@digia.com>
-Date: Mon, 22 Sep 2014 23:13:16 +0300
+From bbfd3cfcf6e1195d86368b61ce39504ce6acda50 Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@theqtcompany.com>
+Date: Wed, 12 Nov 2014 17:09:23 +0200
 Subject: [PATCH 12/16] ANGLE: fix semantic index lookup
 
 The sorted semantic index table was returning a direct mapping to the
@@ -14,10 +14,10 @@ Change-Id: I75d05ed707f56c45210e3dcbc277f894e3dc5a48
  2 files changed, 3 insertions(+), 3 deletions(-)
 
 diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
-index 1085346..3f6d9e0 100644
+index 0619023..6d64b38 100644
 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
-@@ -2788,7 +2788,7 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA
+@@ -1216,7 +1216,7 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA
      for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
      {
          int oldIndex = mAttributesByLayout[i];
@@ -27,10 +27,10 @@ index 1085346..3f6d9e0 100644
      }
  }
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
-index b006c04..d835e4f 100644
+index e41f238..ff90a6a 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
-@@ -112,10 +112,10 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
+@@ -113,10 +113,10 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
              // Record the type of the associated vertex shader vector in our key
              // This will prevent mismatched vertex shaders from using the same input layout
              GLint attributeSize;
@@ -44,5 +44,5 @@ index b006c04..d835e4f 100644
              ilKey.elements[ilKey.elementCount].desc.InputSlot = i;
              ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0;
 -- 
-1.9.0.msysgit.0
+1.9.4.msysgit.1
 
diff --git a/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch b/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch
index 00e32186f00..b43dcc368b0 100644
--- a/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch
+++ b/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch
@@ -1,6 +1,6 @@
-From 3499339ab768017458d3b5295af3742a0f6015db Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@digia.com>
-Date: Mon, 22 Sep 2014 23:15:26 +0300
+From 5ef9348de2624c21be1c9fddd265fec5a0851d25 Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@theqtcompany.com>
+Date: Thu, 13 Nov 2014 15:34:26 +0200
 Subject: [PATCH 13/16] ANGLE: Add support for querying platform device
 
 The EGL_EXT_device_base extension allows for querying the platform
@@ -16,14 +16,14 @@ the IDXGIDevice3::Trim() calls required by the Windows Store.
 
 Change-Id: Ibdf228d81d6604e56db9dd8597d7cd2983ebc428
 ---
- src/3rdparty/angle/src/libEGL/libEGL.cpp | 47 +++++++++++++++++++++++++-------
- 1 file changed, 37 insertions(+), 10 deletions(-)
+ src/3rdparty/angle/src/libEGL/libEGL.cpp | 50 +++++++++++++++++++++++++-------
+ 1 file changed, 39 insertions(+), 11 deletions(-)
 
 diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp
-index 7ea11c5..c2e0fd6 100644
+index dc20d85..68399d6 100644
 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp
 +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp
-@@ -18,6 +18,9 @@
+@@ -17,6 +17,9 @@
  #include "libGLESv2/Texture.h"
  #include "libGLESv2/main.h"
  #include "libGLESv2/renderer/SwapChain.h"
@@ -33,7 +33,7 @@ index 7ea11c5..c2e0fd6 100644
  
  #include "libEGL/main.h"
  #include "libEGL/Display.h"
-@@ -484,24 +487,48 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
+@@ -582,25 +585,50 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
      egl::Display *display = static_cast<egl::Display*>(dpy);
      egl::Surface *eglSurface = (egl::Surface*)surface;
  
@@ -44,7 +44,8 @@ index 7ea11c5..c2e0fd6 100644
 -
 -    if (surface == EGL_NO_SURFACE)
 -    {
--        return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
+-        recordError(egl::Error(EGL_BAD_SURFACE));
+-        return EGL_FALSE;
 -    }
 -
      switch (attribute)
@@ -58,7 +59,8 @@ index 7ea11c5..c2e0fd6 100644
 +
 +            if (surface == EGL_NO_SURFACE)
 +            {
-+                return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
++                recordError(egl::Error(EGL_BAD_SURFACE));
++                return EGL_FALSE;
 +            }
 +
              rx::SwapChain *swapchain = eglSurface->getSwapChain();
@@ -82,7 +84,8 @@ index 7ea11c5..c2e0fd6 100644
 +
 +            if (renderer->getMajorShaderModel() < 4)
 +            {
-+                return egl::error(EGL_BAD_CONTEXT, EGL_FALSE);
++                recordError(egl::Error(EGL_BAD_CONTEXT));
++                return EGL_FALSE;
 +            }
 +
 +            *value = static_cast<rx::Renderer11*>(renderer)->getDevice();
@@ -90,8 +93,8 @@ index 7ea11c5..c2e0fd6 100644
 +        break;
 +#endif
        default:
-         return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
-     }
+         recordError(egl::Error(EGL_BAD_ATTRIBUTE));
+         return EGL_FALSE;
 -- 
-1.9.0.msysgit.0
+1.9.4.msysgit.1
 
diff --git a/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch b/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch
index b884f7b549f..9ceb34d964a 100644
--- a/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch
+++ b/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch
@@ -1,6 +1,6 @@
-From a3046fef7f754f06937161e779ce0a651e77317b Mon Sep 17 00:00:00 2001
+From 5b3bc73210ed1847d9bd7a94f06cc0d5de8e0b89 Mon Sep 17 00:00:00 2001
 From: Michael Bruning <michael.bruning@digia.com>
-Date: Mon, 22 Sep 2014 23:23:40 +0300
+Date: Thu, 13 Nov 2014 15:40:10 +0200
 Subject: [PATCH 14/16] Let ANGLE use multithreaded devices if necessary.
 
 This is needed to prevent lock-ups in application that use ANGLE from
@@ -11,13 +11,13 @@ communicate this from the QtWebEngine module.
 
 Change-Id: Ibd5a5c75eb68af567d420d9a35efb3490c93b27c
 ---
- src/3rdparty/angle/src/common/platform.h                    |  1 +
- .../angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp   | 13 +++++++++++++
- .../angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp     |  4 ++++
- 3 files changed, 18 insertions(+)
+ src/3rdparty/angle/src/common/platform.h                       |  1 +
+ .../angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp      | 10 ++++++++++
+ .../angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp        |  4 ++++
+ 3 files changed, 15 insertions(+)
 
 diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
-index 387ba41..7d0d957 100644
+index 0065ec7..8b2190d 100644
 --- a/src/3rdparty/angle/src/common/platform.h
 +++ b/src/3rdparty/angle/src/common/platform.h
 @@ -57,6 +57,7 @@
@@ -26,17 +26,16 @@ index 387ba41..7d0d957 100644
  #       include <d3d10_1.h>
 +#       include <d3d10.h>
  #       include <d3d11.h>
+ #       include <d3d11_1.h>
  #       include <dxgi.h>
- #       include <dxgi1_2.h>
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-index b4b26a8..bd07ee1 100644
+index f6ba930..46b9984 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-@@ -301,6 +301,19 @@ EGLint Renderer11::initialize()
+@@ -258,6 +258,16 @@ EGLint Renderer11::initialize()
      }
- #endif
  
-+#if !defined(ANGLE_PLATFORM_WINRT)
+ #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
 +    static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
 +    if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
 +    {
@@ -47,16 +46,14 @@ index b4b26a8..bd07ee1 100644
 +        ASSERT(SUCCEEDED(result));
 +        multithread->Release();
 +    }
-+#endif
-+
-     initializeDevice();
- 
-     return EGL_SUCCESS;
+ #if !ANGLE_SKIP_DXGI_1_2_CHECK
+     // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required.
+     // The easiest way to check is to query for a IDXGIDevice2.
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-index e8564bd..1d52705 100644
+index 82963ec..4c552b2 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-@@ -304,6 +304,10 @@ EGLint Renderer9::initialize()
+@@ -299,6 +299,10 @@ EGLint Renderer9::initialize()
      D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
      DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
  
@@ -68,5 +65,5 @@ index e8564bd..1d52705 100644
          result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
      }
 -- 
-1.9.0.msysgit.0
+1.9.4.msysgit.1
 
diff --git a/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch b/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch
index 7d914766a0c..f78474f11a5 100644
--- a/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch
+++ b/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch
@@ -1,23 +1,28 @@
-From 373b3f67352e9a6f599c6a9dd9aee3b4836e0a3f Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@digia.com>
-Date: Mon, 22 Sep 2014 23:41:48 +0300
+From d9a9219ea2181dd4c1939d05747a21b67f16a906 Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@theqtcompany.com>
+Date: Thu, 13 Nov 2014 16:33:53 +0200
 Subject: [PATCH 15/16] ANGLE: Fix -angle-d3d11 on MSVC2010
 
 Allow the D3D11 renderer to build with the June 2010 DirectX SDK.
 
 Change-Id: I2343acedab16845d6a0d4a53cf3145f583efc4a7
 ---
- src/3rdparty/angle/src/common/platform.h           |  6 ++
- .../renderer/d3d/d3d11/renderer11_utils.cpp        | 89 ++++++++++++++++++++++
- 2 files changed, 95 insertions(+)
+ src/3rdparty/angle/src/common/platform.h           |   8 +-
+ src/3rdparty/angle/src/libGLESv2/Context.cpp       |   8 +-
+ src/3rdparty/angle/src/libGLESv2/Data.h            |   2 +-
+ src/3rdparty/angle/src/libGLESv2/State.cpp         |   6 +-
+ .../src/libGLESv2/renderer/d3d/RendererD3D.cpp     |   4 +-
+ .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp    |   4 +-
+ .../renderer/d3d/d3d11/renderer11_utils.cpp        | 137 +++++++++++++++++++++
+ 7 files changed, 156 insertions(+), 13 deletions(-)
 
 diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
-index 7d0d957..3c619f3 100644
+index 8b2190d..972eee2 100644
 --- a/src/3rdparty/angle/src/common/platform.h
 +++ b/src/3rdparty/angle/src/common/platform.h
-@@ -52,7 +52,9 @@
+@@ -52,17 +52,23 @@
  
- #   if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_PERF)
+ #   if defined(ANGLE_ENABLE_D3D9)
  #       include <d3d9.h>
 +#      if !defined(COMPILER_IMPLEMENTATION)
  #       include <d3dcompiler.h>
@@ -25,11 +30,13 @@ index 7d0d957..3c619f3 100644
  #   endif
  
  #   if defined(ANGLE_ENABLE_D3D11)
-@@ -60,8 +62,12 @@
+ #       include <d3d10_1.h>
  #       include <d3d10.h>
  #       include <d3d11.h>
+-#       include <d3d11_1.h>
  #       include <dxgi.h>
-+#      if _MSC_VER >= 1700
++#      if defined(_MSC_VER) && (_MSC_VER >= 1700)
++#       include <d3d11_1.h>
  #       include <dxgi1_2.h>
 +#      endif
 +#      if !defined(COMPILER_IMPLEMENTATION)
@@ -37,12 +44,118 @@ index 7d0d957..3c619f3 100644
 +#      endif
  #   endif
  
- #   undef near
+ #   if defined(ANGLE_ENABLE_WINDOWS_STORE)
+diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp
+index fe9b1a2..b87689c 100644
+--- a/src/3rdparty/angle/src/libGLESv2/Context.cpp
++++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp
+@@ -168,9 +168,9 @@ Context::~Context()
+     }
+     mIncompleteTextures.clear();
+ 
+-    for (auto &zeroTexture : mZeroTextures)
++    for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++)
+     {
+-        zeroTexture.second.set(NULL);
++        i->second.set(NULL);
+     }
+     mZeroTextures.clear();
+ 
+@@ -354,7 +354,7 @@ void Context::deleteFenceSync(GLsync fenceSync)
+ 
+ void Context::deleteVertexArray(GLuint vertexArray)
+ {
+-    auto vertexArrayObject = mVertexArrayMap.find(vertexArray);
++    VertexArrayMap::iterator vertexArrayObject = mVertexArrayMap.find(vertexArray);
+ 
+     if (vertexArrayObject != mVertexArrayMap.end())
+     {
+@@ -460,7 +460,7 @@ FenceSync *Context::getFenceSync(GLsync handle) const
+ 
+ VertexArray *Context::getVertexArray(GLuint handle) const
+ {
+-    auto vertexArray = mVertexArrayMap.find(handle);
++    VertexArrayMap::const_iterator vertexArray = mVertexArrayMap.find(handle);
+ 
+     if (vertexArray == mVertexArrayMap.end())
+     {
+diff --git a/src/3rdparty/angle/src/libGLESv2/Data.h b/src/3rdparty/angle/src/libGLESv2/Data.h
+index cff872a..9234403 100644
+--- a/src/3rdparty/angle/src/libGLESv2/Data.h
++++ b/src/3rdparty/angle/src/libGLESv2/Data.h
+@@ -14,7 +14,7 @@
+ namespace gl
+ {
+ 
+-struct Data final
++struct Data
+ {
+   public:
+     Data(GLint clientVersion, const State &state, const Caps &caps,
+diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libGLESv2/State.cpp
+index e7acda2..b5b62f5 100644
+--- a/src/3rdparty/angle/src/libGLESv2/State.cpp
++++ b/src/3rdparty/angle/src/libGLESv2/State.cpp
+@@ -665,13 +665,13 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture)
+ 
+ void State::initializeZeroTextures(const TextureMap &zeroTextures)
+ {
+-    for (const auto &zeroTexture : zeroTextures)
++    for (TextureMap::const_iterator i = zeroTextures.begin(); i != zeroTextures.end(); i++)
+     {
+-        auto &samplerTextureArray = mSamplerTextures[zeroTexture.first];
++        TextureBindingVector &samplerTextureArray = mSamplerTextures[i->first];
+ 
+         for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit)
+         {
+-            samplerTextureArray[textureUnit].set(zeroTexture.second.get());
++            samplerTextureArray[textureUnit].set(i->second.get());
+         }
+     }
+ }
+diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
+index 6f58243..97da6da 100644
+--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
+@@ -27,9 +27,9 @@ RendererD3D::RendererD3D(egl::Display *display)
+ 
+ RendererD3D::~RendererD3D()
+ {
+-    for (auto &incompleteTexture : mIncompleteTextures)
++    for (gl::TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); ++i)
+     {
+-        incompleteTexture.second.set(NULL);
++        i->second.set(NULL);
+     }
+     mIncompleteTextures.clear();
+ }
+diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
+index 46b9984..a28fd78 100644
+--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
+@@ -873,7 +873,7 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
+ 
+ void Renderer11::unsetSRVsWithResource(gl::SamplerType samplerType, const ID3D11Resource *resource)
+ {
+-    auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
++    std::vector<ID3D11ShaderResourceView *> &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+ 
+     for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex)
+     {
+@@ -3398,7 +3398,7 @@ Workarounds Renderer11::generateWorkarounds() const
+ 
+ void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv)
+ {
+-    auto &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
++    std::vector<ID3D11ShaderResourceView *> &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+ 
+     ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size());
+ 
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-index 06a22eb..345fd24 100644
+index cbfe557..5831c57 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-@@ -17,6 +17,37 @@
+@@ -18,6 +18,85 @@
  
  #include <algorithm>
  
@@ -76,300 +189,348 @@ index 06a22eb..345fd24 100644
 +#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION
 +#  define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096
 +#endif
++#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION
++#  define D3D11_REQ_TEXTURECUBE_DIMENSION 16384
++#endif
++#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION
++#  define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048
++#endif
++#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
++#  define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048
++#endif
++#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP
++#  define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32
++#endif
++#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP
++#  define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32
++#endif
++#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT
++#  define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32
++#endif
++#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT
++#  define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32
++#endif
++#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT
++#  define D3D10_1_SO_BUFFER_SLOT_COUNT 4
++#endif
++#ifndef D3D11_SO_BUFFER_SLOT_COUNT
++#  define D3D11_SO_BUFFER_SLOT_COUNT 4
++#endif
++#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
++#  define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14
++#endif
++#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT
++#  define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16
++#endif
++#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
++#  define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8
++#endif
++#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
++#  define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7
++#endif
++#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT
++#  define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096
++#endif
++#ifndef D3D11_PS_INPUT_REGISTER_COUNT
++#  define D3D11_PS_INPUT_REGISTER_COUNT 32
++#endif
++#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT
++#  define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32
++#endif
 +
  namespace rx
  {
  
-@@ -275,7 +306,9 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
+@@ -276,7 +355,9 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0:
        case D3D_FEATURE_LEVEL_10_1:
        case D3D_FEATURE_LEVEL_10_0: return true;
-@@ -293,7 +326,9 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
+@@ -294,7 +375,9 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -313,7 +348,9 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+@@ -314,7 +397,9 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0:
        case D3D_FEATURE_LEVEL_10_1:
        case D3D_FEATURE_LEVEL_10_0: return true;
-@@ -333,7 +370,9 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+@@ -334,7 +419,9 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
  
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0:
        case D3D_FEATURE_LEVEL_10_1:
        case D3D_FEATURE_LEVEL_10_0:
-@@ -351,7 +390,9 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
+@@ -352,7 +439,9 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
  
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0:
        case D3D_FEATURE_LEVEL_10_1:
        case D3D_FEATURE_LEVEL_10_0:
-@@ -374,7 +415,9 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
+@@ -375,7 +464,9 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
  
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0:
        case D3D_FEATURE_LEVEL_10_1:
        case D3D_FEATURE_LEVEL_10_0:
-@@ -392,7 +435,9 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel
+@@ -393,7 +484,9 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel
  
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -410,7 +455,9 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+@@ -411,7 +504,9 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -428,7 +475,9 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
+@@ -429,7 +524,9 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -446,7 +495,9 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
+@@ -447,7 +544,9 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -464,7 +515,9 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+@@ -465,7 +564,9 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -482,7 +535,9 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
+@@ -483,7 +584,9 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -506,7 +561,9 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)
+@@ -507,7 +610,9 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)
  
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0:
        case D3D_FEATURE_LEVEL_10_1:
        case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits<GLint>::max();
-@@ -528,7 +585,9 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)
+@@ -529,7 +634,9 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)
  
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0:
        case D3D_FEATURE_LEVEL_10_1:
        case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits<GLint>::max();
-@@ -545,7 +604,9 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
+@@ -546,7 +653,9 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT;
  
        case D3D_FEATURE_LEVEL_10_1: return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT;
-@@ -565,7 +626,9 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+@@ -566,7 +675,9 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
      // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -590,7 +653,9 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+@@ -591,7 +702,9 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers();
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -617,7 +682,9 @@ static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
+@@ -618,7 +731,9 @@ static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
  
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
  
        case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
-@@ -636,7 +703,9 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+@@ -637,7 +752,9 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -658,7 +727,9 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+@@ -659,7 +776,9 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
      // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -683,7 +754,9 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+@@ -684,7 +803,9 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers();
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -702,7 +775,9 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
+@@ -703,7 +824,9 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -721,7 +796,9 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+@@ -722,7 +845,9 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -740,7 +817,9 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
+@@ -741,7 +866,9 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -759,7 +838,9 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
+@@ -760,7 +887,9 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
        case D3D_FEATURE_LEVEL_10_1:
        case D3D_FEATURE_LEVEL_10_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
-@@ -782,7 +863,9 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)
+@@ -783,7 +912,9 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)
  
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -801,7 +884,9 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
+@@ -802,7 +933,9 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT;
  
        case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SO_BUFFER_SLOT_COUNT;
-@@ -819,7 +904,9 @@ static size_t GetMaximumStreamOutputInterleavedComponenets(D3D_FEATURE_LEVEL fea
+@@ -820,7 +953,9 @@ static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL feat
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
        case D3D_FEATURE_LEVEL_11_0:
  
        case D3D_FEATURE_LEVEL_10_1:
-@@ -837,7 +924,9 @@ static size_t GetMaximumStreamOutputSeparateCompeonents(D3D_FEATURE_LEVEL featur
+@@ -838,7 +973,9 @@ static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL feature
  {
      switch (featureLevel)
      {
-+#if _MSC_VER >= 1700
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
        case D3D_FEATURE_LEVEL_11_1:
 +#endif
-       case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponenets(featureLevel) /
+       case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) /
                                            GetMaximumStreamOutputBuffers(featureLevel);
  
 -- 
-1.9.0.msysgit.0
+1.9.4.msysgit.1
 
diff --git a/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch b/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch
index 2ea528018d9..e3df95d8bf7 100644
--- a/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch
+++ b/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch
@@ -1,35 +1,29 @@
-From 75c39e9020f062d155097f6b49aebbc12970b1e8 Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@digia.com>
-Date: Tue, 23 Sep 2014 23:39:14 +0300
+From 43c8ceb17ccd6d5ae13a07c6d01b45eb40983917 Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@theqtcompany.com>
+Date: Tue, 11 Nov 2014 14:36:43 +0200
 Subject: [PATCH 16/16] ANGLE: Fix compilation with MinGW + D3D11
 
-Provide workarounds for things GCC doesn't like, and define a number
-of macros not found in the MinGW headers.
+Provide workarounds for things GCC doesn't like, and define a few
+missing definitions not found in the MinGW headers.
 
 Change-Id: I254c208209c0071fae5efb6727f2b3cfd5542da6
 ---
- src/3rdparty/angle/src/common/platform.h           | 11 +++++
- src/3rdparty/angle/src/libEGL/Display.cpp          |  1 +
- src/3rdparty/angle/src/libGLESv2/Context.cpp       |  5 +-
- src/3rdparty/angle/src/libGLESv2/angletypes.h      |  1 +
- .../angle/src/libGLESv2/renderer/copyimage.inl     |  2 +-
- .../src/libGLESv2/renderer/d3d/TextureD3D.cpp      |  4 +-
+ src/3rdparty/angle/src/common/platform.h           | 73 ++++++++++++++++++++++
+ .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp    |  6 ++
  .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp    |  2 +-
- .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp   |  2 +-
- .../renderer/d3d/d3d11/renderer11_utils.cpp        | 53 +++++++++++++++++++++-
+ .../renderer/d3d/d3d11/renderer11_utils.cpp        |  2 +-
  .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp  |  4 +-
- src/3rdparty/angle/src/libGLESv2/validationES.cpp  |  2 +-
- 11 files changed, 76 insertions(+), 11 deletions(-)
+ 5 files changed, 83 insertions(+), 4 deletions(-)
 
 diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
-index 3c619f3..b53394f 100644
+index 972eee2..0001e71 100644
 --- a/src/3rdparty/angle/src/common/platform.h
 +++ b/src/3rdparty/angle/src/common/platform.h
-@@ -68,6 +68,17 @@
- #      if !defined(COMPILER_IMPLEMENTATION)
- #       include <d3dcompiler.h>
- #      endif
-+#      if defined(__MINGW32__)
+@@ -81,6 +81,79 @@
+ #       endif
+ #   endif
+ 
++#  if defined(__MINGW32__) // Missing defines on MinGW
 +typedef enum D3D11_MAP_FLAG
 +{
 +    D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L
@@ -39,202 +33,121 @@ index 3c619f3..b53394f 100644
 +    UINT64 NumPrimitivesWritten;
 +    UINT64 PrimitivesStorageNeeded;
 +} D3D11_QUERY_DATA_SO_STATISTICS;
-+#      endif
- #   endif
- 
++typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)(
++        IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *,
++        UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **);
++#define D3D11_MESSAGE_CATEGORY UINT
++#define D3D11_MESSAGE_SEVERITY UINT
++#define D3D11_MESSAGE_ID UINT
++struct D3D11_MESSAGE;
++typedef struct D3D11_INFO_QUEUE_FILTER_DESC
++{
++    UINT NumCategories;
++    D3D11_MESSAGE_CATEGORY *pCategoryList;
++    UINT NumSeverities;
++    D3D11_MESSAGE_SEVERITY *pSeverityList;
++    UINT NumIDs;
++    D3D11_MESSAGE_ID *pIDList;
++} D3D11_INFO_QUEUE_FILTER_DESC;
++typedef struct D3D11_INFO_QUEUE_FILTER
++{
++    D3D11_INFO_QUEUE_FILTER_DESC AllowList;
++    D3D11_INFO_QUEUE_FILTER_DESC DenyList;
++} D3D11_INFO_QUEUE_FILTER;
++static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 };
++MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown
++{
++public:
++    virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0;
++    virtual void __stdcall ClearStoredMessages() = 0;
++    virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0;
++    virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0;
++    virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0;
++    virtual UINT64 __stdcall GetNumStoredMessages() = 0;
++    virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0;
++    virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0;
++    virtual UINT64 __stdcall GetMessageCountLimit() = 0;
++    virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
++    virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
++    virtual void __stdcall ClearStorageFilter() = 0;
++    virtual HRESULT __stdcall PushEmptyStorageFilter() = 0;
++    virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0;
++    virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
++    virtual void __stdcall PopStorageFilter() = 0;
++    virtual UINT __stdcall GetStorageFilterStackSize() = 0;
++    virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
++    virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
++    virtual void __stdcall ClearRetrievalFilter() = 0;
++    virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0;
++    virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0;
++    virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
++    virtual void __stdcall PopRetrievalFilter() = 0;
++    virtual UINT __stdcall GetRetrievalFilterStackSize() = 0;
++    virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0;
++    virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0;
++    virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0;
++    virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0;
++    virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0;
++    virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0;
++    virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0;
++    virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0;
++    virtual void __stdcall SetMuteDebugOutput(BOOL) = 0;
++    virtual BOOL __stdcall GetMuteDebugOutput() = 0;
++};
++#endif // __MINGW32__
++
  #   undef near
-diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp
-index ba09631..5a50e4b 100644
---- a/src/3rdparty/angle/src/libEGL/Display.cpp
-+++ b/src/3rdparty/angle/src/libEGL/Display.cpp
-@@ -14,6 +14,7 @@
- #include <map>
- #include <vector>
- #include <sstream>
-+#include <iterator>
- 
- #include "common/debug.h"
- #include "common/mathutil.h"
-diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp
-index 04c7616..5342de1 100644
---- a/src/3rdparty/angle/src/libGLESv2/Context.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp
-@@ -33,6 +33,7 @@
- #include "libEGL/Surface.h"
- 
- #include <sstream>
-+#include <iterator>
- 
- namespace gl
- {
-@@ -354,7 +355,7 @@ void Context::deleteFenceSync(GLsync fenceSync)
-     // wait commands finish. However, since the name becomes invalid, we cannot query the fence,
-     // and since our API is currently designed for being called from a single thread, we can delete
-     // the fence immediately.
--    mResourceManager->deleteFenceSync(reinterpret_cast<GLuint>(fenceSync));
-+    mResourceManager->deleteFenceSync(uintptr_t(fenceSync));
- }
- 
- void Context::deleteVertexArray(GLuint vertexArray)
-@@ -460,7 +461,7 @@ Renderbuffer *Context::getRenderbuffer(GLuint handle)
- 
- FenceSync *Context::getFenceSync(GLsync handle) const
- {
--    return mResourceManager->getFenceSync(reinterpret_cast<GLuint>(handle));
-+    return mResourceManager->getFenceSync(uintptr_t(handle));
- }
- 
- VertexArray *Context::getVertexArray(GLuint handle) const
-diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libGLESv2/angletypes.h
-index 922053e..642a6ec 100644
---- a/src/3rdparty/angle/src/libGLESv2/angletypes.h
-+++ b/src/3rdparty/angle/src/libGLESv2/angletypes.h
-@@ -11,6 +11,7 @@
- 
- #include "libGLESv2/constants.h"
- #include "common/RefCountObject.h"
-+#include <float.h>
- 
- namespace gl
- {
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl
-index ea6970c..0498cf7 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl
-@@ -24,7 +24,7 @@ inline void WriteColor(const uint8_t *source, uint8_t *dest)
- template <typename sourceType, typename destType, typename colorDataType>
- inline void CopyPixel(const uint8_t *source, uint8_t *dest)
- {
--    colorType temp;
-+    colorDataType temp;
-     ReadColor<sourceType, colorDataType>(source, &temp);
-     WriteColor<destType, colorDataType>(&temp, dest);
- }
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp
-index 2650913..96c8497 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp
-@@ -129,7 +129,7 @@ bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei w
-     if (unpack.pixelBuffer.id() != 0)
-     {
-         gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
--        unsigned int offset = reinterpret_cast<unsigned int>(pixels);
-+        ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
-         // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data.
-         // This functionality should be moved into renderer and the getData method of BufferImpl removed.
-         const void *bufferData = pixelBuffer->getImplementation()->getData();
-@@ -186,7 +186,7 @@ bool TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void
-     // to create a render target.
-     ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat));
- 
--    unsigned int offset = reinterpret_cast<unsigned int>(pixels);
-+    ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
+ #   undef far
+ #endif
+diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
+index 9d003b4..776d92b 100644
+--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
+@@ -14,6 +14,12 @@
+ #ifndef QT_D3DCOMPILER_DLL
+ #define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL
+ #endif
++#ifndef D3DCOMPILE_RESERVED16
++#define D3DCOMPILE_RESERVED16 (1 << 16)
++#endif
++#ifndef D3DCOMPILE_RESERVED17
++#define D3DCOMPILE_RESERVED17 (1 << 17)
++#endif
  
-     return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea);
- }
+ // Definitions local to the translation unit
+ namespace
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-index bd07ee1..b29b2ef 100644
+index a28fd78..e6d7f30 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-@@ -281,7 +281,7 @@ EGLint Renderer11::initialize()
-     }
- 
+@@ -333,7 +333,7 @@ EGLint Renderer11::initialize()
      // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
--#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
-+#if !defined(__MINGW32__) && defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
+ #if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
      ID3D11InfoQueue *infoQueue;
-     result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue),  (void **)&infoQueue);
+-    result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue),  (void **)&infoQueue);
++    result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue);
  
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
-index 787c511..4b29be0 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
-@@ -537,7 +537,7 @@ void SwapChain11::initPassThroughResources()
-     samplerDesc.BorderColor[2] = 0.0f;
-     samplerDesc.BorderColor[3] = 0.0f;
-     samplerDesc.MinLOD = 0;
--    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
-+    samplerDesc.MaxLOD = FLT_MAX;
- 
-     result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
-     ASSERT(SUCCEEDED(result));
+     if (SUCCEEDED(result))
+     {
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-index 345fd24..2af97e7 100644
+index 5831c57..121aa3b 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-@@ -47,6 +47,57 @@
- #ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION
- #  define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096
- #endif
-+#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION
-+#  define D3D11_REQ_TEXTURECUBE_DIMENSION 16384
-+#endif
-+#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION
-+#  define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048
-+#endif
-+#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
-+#  define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048
-+#endif
-+#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP
-+#  define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32
-+#endif
-+#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP
-+#  define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32
-+#endif
-+#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT
-+#  define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32
-+#endif
-+#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT
-+#  define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32
-+#endif
-+#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT
-+#  define D3D10_1_SO_BUFFER_SLOT_COUNT 4
-+#endif
-+#ifndef D3D11_SO_BUFFER_SLOT_COUNT
-+#  define D3D11_SO_BUFFER_SLOT_COUNT 4
-+#endif
-+#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
-+#  define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14
-+#endif
-+#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT
-+#  define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16
-+#endif
-+#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
-+#  define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8
-+#endif
-+#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
-+#  define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7
-+#endif
-+#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT
-+#  define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096
-+#endif
-+#ifndef D3D11_PS_INPUT_REGISTER_COUNT
-+#  define D3D11_PS_INPUT_REGISTER_COUNT 32
-+#endif
-+#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT
-+#  define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32
-+#endif
-+#ifndef D3D11_VS_OUTPUT_REGISTER_COUNT
-+#  define D3D11_VS_OUTPUT_REGISTER_COUNT 32
-+#endif
- 
- namespace rx
- {
-@@ -1147,7 +1198,7 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo
+@@ -1196,7 +1196,7 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo
  
  HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
  {
 -#if defined(_DEBUG)
-+#if !defined(__MINGW32__) && defined(_DEBUG)
++#if defined(_DEBUG) && !defined(__MINGW32__)
      return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name);
  #else
      return S_OK;
 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-index 1d52705..d63f9b8 100644
+index 4c552b2..601cd24 100644
 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
 +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-@@ -205,7 +205,7 @@ EGLint Renderer9::initialize()
-     if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
+@@ -200,7 +200,7 @@ EGLint Renderer9::initialize()
+     if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
      {
          ASSERT(mD3d9Ex);
 -        mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void**>(&mD3d9));
@@ -242,7 +155,7 @@ index 1d52705..d63f9b8 100644
          ASSERT(mD3d9);
      }
      else
-@@ -329,7 +329,7 @@ EGLint Renderer9::initialize()
+@@ -324,7 +324,7 @@ EGLint Renderer9::initialize()
  
      if (mD3d9Ex)
      {
@@ -251,19 +164,6 @@ index 1d52705..d63f9b8 100644
          ASSERT(SUCCEEDED(result));
      }
  
-diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.cpp b/src/3rdparty/angle/src/libGLESv2/validationES.cpp
-index 1b6180d..f79bc97 100644
---- a/src/3rdparty/angle/src/libGLESv2/validationES.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/validationES.cpp
-@@ -1667,7 +1667,7 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t
-     // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
-     if (elementArrayBuffer)
-     {
--        unsigned int offset = reinterpret_cast<unsigned int>(indices);
-+        GLint64 offset = reinterpret_cast<GLint64>(indices);
-         if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL))
-         {
-             const void *dataPointer = elementArrayBuffer->getImplementation()->getData();
 -- 
-1.9.0.msysgit.0
+1.9.4.msysgit.1
 
diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro
index 48ce7055fd8..a16249309f4 100644
--- a/src/angle/src/libEGL/libEGL.pro
+++ b/src/angle/src/libEGL/libEGL.pro
@@ -6,20 +6,40 @@ winrt: LIBS_PRIVATE += -ld3d11
 LIBS_PRIVATE += -ldxguid -L$$QT_BUILD_TREE/lib -l$$qtLibraryTarget(libGLESv2)
 
 HEADERS += \
+    $$ANGLE_DIR/src/common/NativeWindow.h \
+    $$ANGLE_DIR/src/libEGL/AttributeMap.h \
     $$ANGLE_DIR/src/libEGL/Config.h \
     $$ANGLE_DIR/src/libEGL/Display.h \
+    $$ANGLE_DIR/src/libEGL/Error.h \
     $$ANGLE_DIR/src/libEGL/main.h \
     $$ANGLE_DIR/src/libEGL/resource.h \
     $$ANGLE_DIR/src/libEGL/ShaderCache.h \
     $$ANGLE_DIR/src/libEGL/Surface.h
 
 SOURCES += \
+    $$ANGLE_DIR/src/libEGL/AttributeMap.cpp \
     $$ANGLE_DIR/src/libEGL/Config.cpp \
     $$ANGLE_DIR/src/libEGL/Display.cpp \
+    $$ANGLE_DIR/src/libEGL/Error.cpp \
     $$ANGLE_DIR/src/libEGL/libEGL.cpp \
     $$ANGLE_DIR/src/libEGL/main.cpp \
     $$ANGLE_DIR/src/libEGL/Surface.cpp
 
+!winrt {
+    SOURCES += \
+        $$ANGLE_DIR/src/common/win32/NativeWindow.cpp
+} else {
+    HEADERS += \
+        $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.h \
+        $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.h \
+        $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.h
+
+    SOURCES += \
+        $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.cpp \
+        $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.cpp \
+        $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.cpp
+}
+
 !static {
     DEF_FILE = $$ANGLE_DIR/src/libEGL/$${TARGET}.def
     mingw:equals(QT_ARCH, i386): DEF_FILE = $$ANGLE_DIR/src/libEGL/$${TARGET}_mingw32.def
diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro
index c0f7982e6c6..705768d17d7 100644
--- a/src/angle/src/libGLESv2/libGLESv2.pro
+++ b/src/angle/src/libGLESv2/libGLESv2.pro
@@ -24,11 +24,13 @@ HEADERS += \
     $$ANGLE_DIR/src/common/blocklayout.h \
     $$ANGLE_DIR/src/common/shadervars.h \
     $$ANGLE_DIR/src/common/utilities.h \
+    $$ANGLE_DIR/src/common/NativeWindow.h \
     $$ANGLE_DIR/src/libGLESv2/angletypes.h \
     $$ANGLE_DIR/src/libGLESv2/BinaryStream.h \
     $$ANGLE_DIR/src/libGLESv2/Buffer.h \
     $$ANGLE_DIR/src/libGLESv2/Caps.h \
     $$ANGLE_DIR/src/libGLESv2/Context.h \
+    $$ANGLE_DIR/src/libGLESv2/Data.h \
     $$ANGLE_DIR/src/libGLESv2/Error.h \
     $$ANGLE_DIR/src/libGLESv2/Fence.h \
     $$ANGLE_DIR/src/libGLESv2/formatutils.h \
@@ -53,6 +55,8 @@ HEADERS += \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/IndexDataManager.h \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/MemoryBuffer.h \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ProgramD3D.h \
+    $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RenderbufferD3D.h \
+    $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RendererD3D.h \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ShaderD3D.h \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureD3D.h \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureStorage.h \
@@ -69,6 +73,7 @@ HEADERS += \
     $$ANGLE_DIR/src/libGLESv2/renderer/loadimage.h \
     $$ANGLE_DIR/src/libGLESv2/renderer/ProgramImpl.h \
     $$ANGLE_DIR/src/libGLESv2/renderer/QueryImpl.h \
+    $$ANGLE_DIR/src/libGLESv2/renderer/RenderbufferImpl.h \
     $$ANGLE_DIR/src/libGLESv2/renderer/Renderer.h \
     $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget.h \
     $$ANGLE_DIR/src/libGLESv2/renderer/ShaderExecutable.h \
@@ -77,6 +82,7 @@ HEADERS += \
     $$ANGLE_DIR/src/libGLESv2/renderer/TextureImpl.h \
     $$ANGLE_DIR/src/libGLESv2/renderer/TextureFeedbackImpl.h \
     $$ANGLE_DIR/src/libGLESv2/renderer/VertexDeclarationCache.h \
+    $$ANGLE_DIR/src/libGLESv2/renderer/Workarounds.h \
     $$ANGLE_DIR/src/libGLESv2/resource.h \
     $$ANGLE_DIR/src/libGLESv2/ResourceManager.h \
     $$ANGLE_DIR/src/libGLESv2/Sampler.h \
@@ -102,6 +108,7 @@ SOURCES += \
     $$ANGLE_DIR/src/libGLESv2/Buffer.cpp \
     $$ANGLE_DIR/src/libGLESv2/Caps.cpp \
     $$ANGLE_DIR/src/libGLESv2/Context.cpp \
+    $$ANGLE_DIR/src/libGLESv2/Data.cpp \
     $$ANGLE_DIR/src/libGLESv2/Error.cpp \
     $$ANGLE_DIR/src/libGLESv2/Fence.cpp \
     $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.cpp \
@@ -131,10 +138,12 @@ SOURCES += \
     $$ANGLE_DIR/src/libGLESv2/VertexAttribute.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/copyimage.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/loadimage.cpp \
-    $$ANGLE_DIR/src/libGLESv2/renderer/loadimageSSE2.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/Image.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/IndexRangeCache.cpp \
+    $$ANGLE_DIR/src/libGLESv2/renderer/ProgramImpl.cpp \
+    $$ANGLE_DIR/src/libGLESv2/renderer/RenderbufferImpl.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/Renderer.cpp \
+    $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/BufferD3D.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp \
@@ -143,6 +152,8 @@ SOURCES += \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/IndexDataManager.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ProgramD3D.cpp \
+    $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp \
+    $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RendererD3D.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ShaderD3D.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureD3D.cpp \
     $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureStorage.cpp \
@@ -192,6 +203,8 @@ angle_d3d11 {
         $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp
 }
 
+SSE2_SOURCES += $$ANGLE_DIR/src/libGLESv2/renderer/loadimageSSE2.cpp
+
 !winrt {
     HEADERS += \
         $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Blit9.h \
@@ -211,6 +224,7 @@ angle_d3d11 {
         $$ANGLE_DIR/src/third_party/systeminfo/SystemInfo.h
 
     SOURCES += \
+        $$ANGLE_DIR/src/common/win32/NativeWindow.cpp \
         $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp \
         $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp \
         $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp \
@@ -227,6 +241,16 @@ angle_d3d11 {
         $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp \
         $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp \
         $$ANGLE_DIR/src/third_party/systeminfo/SystemInfo.cpp
+} else {
+    HEADERS += \
+        $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.h \
+        $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.h \
+        $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.h
+
+    SOURCES += \
+        $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.cpp \
+        $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.cpp \
+        $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.cpp
 }
 
 !static {
-- 
GitLab