Bug 1251375. Update to ANGLE/2653
☠☠ backed out by 8dcacd3fa661 ☠ ☠
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Tue, 15 Mar 2016 12:02:47 -0700
changeset 326700 857617eac45b8177a074a2e55968ba7deeb23609
parent 326699 4f41a072c0ca0523a9e211c521c21190d3b6dc4d
child 326701 8f609479ba372faba7c3e6aa2c3b519eb43ebc84
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1251375
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1251375. Update to ANGLE/2653
dom/canvas/WebGLShaderValidator.cpp
dom/canvas/test/webgl-mochitest.ini
gfx/angle/BUILD.gn
gfx/angle/DEPS
gfx/angle/README.md
gfx/angle/include/EGL/eglext.h
gfx/angle/include/GLES2/gl2ext.h
gfx/angle/include/GLSLANG/ShaderLang.h
gfx/angle/include/GLSLANG/ShaderVars.h
gfx/angle/moz.build
gfx/angle/src/angle.gyp
gfx/angle/src/commit.h
gfx/angle/src/common/BitSetIterator_unittest.cpp
gfx/angle/src/common/Optional.h
gfx/angle/src/common/angleutils.cpp
gfx/angle/src/common/angleutils.h
gfx/angle/src/common/debug.cpp
gfx/angle/src/common/debug.h
gfx/angle/src/common/mathutil.h
gfx/angle/src/compiler.gypi
gfx/angle/src/compiler/translator/CallDAG.cpp
gfx/angle/src/compiler/translator/CodeGen.cpp
gfx/angle/src/compiler/translator/Common.h
gfx/angle/src/compiler/translator/Compiler.cpp
gfx/angle/src/compiler/translator/DirectiveHandler.cpp
gfx/angle/src/compiler/translator/DirectiveHandler.h
gfx/angle/src/compiler/translator/OutputHLSL.cpp
gfx/angle/src/compiler/translator/ParseContext.cpp
gfx/angle/src/compiler/translator/ParseContext.h
gfx/angle/src/compiler/translator/ShaderLang.cpp
gfx/angle/src/compiler/translator/ShaderVars.cpp
gfx/angle/src/compiler/translator/SymbolTable.h
gfx/angle/src/compiler/translator/TranslatorHLSL.cpp
gfx/angle/src/compiler/translator/UniformHLSL.cpp
gfx/angle/src/compiler/translator/UniformHLSL.h
gfx/angle/src/compiler/translator/UtilsHLSL.cpp
gfx/angle/src/compiler/translator/UtilsHLSL.h
gfx/angle/src/compiler/translator/VariableInfo.cpp
gfx/angle/src/compiler/translator/blocklayout.h
gfx/angle/src/compiler/translator/blocklayoutHLSL.cpp
gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h
gfx/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp
gfx/angle/src/compiler/translator/generate_parser.sh
gfx/angle/src/compiler/translator/glslang.y
gfx/angle/src/compiler/translator/glslang_tab.cpp
gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp
gfx/angle/src/libANGLE/Buffer.cpp
gfx/angle/src/libANGLE/Buffer.h
gfx/angle/src/libANGLE/Caps.cpp
gfx/angle/src/libANGLE/Caps.h
gfx/angle/src/libANGLE/Config.cpp
gfx/angle/src/libANGLE/Config.h
gfx/angle/src/libANGLE/Context.cpp
gfx/angle/src/libANGLE/Context.h
gfx/angle/src/libANGLE/Data.cpp
gfx/angle/src/libANGLE/Data.h
gfx/angle/src/libANGLE/Debug.cpp
gfx/angle/src/libANGLE/Debug.h
gfx/angle/src/libANGLE/Display.cpp
gfx/angle/src/libANGLE/Display.h
gfx/angle/src/libANGLE/Error.cpp
gfx/angle/src/libANGLE/Error.h
gfx/angle/src/libANGLE/Error.inl
gfx/angle/src/libANGLE/Fence.cpp
gfx/angle/src/libANGLE/Fence.h
gfx/angle/src/libANGLE/Framebuffer.cpp
gfx/angle/src/libANGLE/Framebuffer.h
gfx/angle/src/libANGLE/HandleAllocator.cpp
gfx/angle/src/libANGLE/HandleAllocator.h
gfx/angle/src/libANGLE/Program.cpp
gfx/angle/src/libANGLE/Program.h
gfx/angle/src/libANGLE/Query.cpp
gfx/angle/src/libANGLE/Query.h
gfx/angle/src/libANGLE/RefCountObject.cpp
gfx/angle/src/libANGLE/RefCountObject.h
gfx/angle/src/libANGLE/Renderbuffer.cpp
gfx/angle/src/libANGLE/Renderbuffer.h
gfx/angle/src/libANGLE/Sampler.cpp
gfx/angle/src/libANGLE/Sampler.h
gfx/angle/src/libANGLE/Shader.cpp
gfx/angle/src/libANGLE/Shader.h
gfx/angle/src/libANGLE/State.cpp
gfx/angle/src/libANGLE/State.h
gfx/angle/src/libANGLE/Surface.cpp
gfx/angle/src/libANGLE/Surface.h
gfx/angle/src/libANGLE/Surface_unittest.cpp
gfx/angle/src/libANGLE/Texture.cpp
gfx/angle/src/libANGLE/Texture.h
gfx/angle/src/libANGLE/TransformFeedback.cpp
gfx/angle/src/libANGLE/TransformFeedback.h
gfx/angle/src/libANGLE/VertexArray.cpp
gfx/angle/src/libANGLE/VertexArray.h
gfx/angle/src/libANGLE/formatutils.cpp
gfx/angle/src/libANGLE/moz.build
gfx/angle/src/libANGLE/renderer/DisplayImpl.h
gfx/angle/src/libANGLE/renderer/FramebufferImpl.h
gfx/angle/src/libANGLE/renderer/FramebufferImpl_mock.h
gfx/angle/src/libANGLE/renderer/ProgramImpl_mock.h
gfx/angle/src/libANGLE/renderer/QueryImpl.h
gfx/angle/src/libANGLE/renderer/Renderer.h
gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/CompilerD3D.h
gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
gfx/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.h
gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
gfx/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/RendererD3D.h
gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.py
gfx/angle/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
gfx/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json
gfx/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_util.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h
gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h
gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h
gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
gfx/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h
gfx/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp
gfx/angle/src/libANGLE/renderer/d3d/loadimage_etc.h
gfx/angle/src/libANGLE/renderer/gl/DisplayGL.cpp
gfx/angle/src/libANGLE/renderer/gl/DisplayGL.h
gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.h
gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.cpp
gfx/angle/src/libANGLE/renderer/gl/FunctionsGL.h
gfx/angle/src/libANGLE/renderer/gl/QueryGL.cpp
gfx/angle/src/libANGLE/renderer/gl/QueryGL.h
gfx/angle/src/libANGLE/renderer/gl/RendererGL.cpp
gfx/angle/src/libANGLE/renderer/gl/RendererGL.h
gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
gfx/angle/src/libANGLE/renderer/gl/StateManagerGL.h
gfx/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp
gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.h
gfx/angle/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm
gfx/angle/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
gfx/angle/src/libANGLE/renderer/gl/formatutilsgl.cpp
gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
gfx/angle/src/libANGLE/renderer/gl/glx/DisplayGLX.h
gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.cpp
gfx/angle/src/libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h
gfx/angle/src/libANGLE/renderer/gl/glx/SurfaceGLX.h
gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp
gfx/angle/src/libANGLE/renderer/gl/glx/WindowSurfaceGLX.h
gfx/angle/src/libANGLE/renderer/gl/glx/platform_glx.h
gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.h
gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp
gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h
gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h
gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp
gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h
gfx/angle/src/libANGLE/validationEGL.cpp
gfx/angle/src/libANGLE/validationEGL.h
gfx/angle/src/libANGLE/validationES.cpp
gfx/angle/src/libANGLE/validationES.h
gfx/angle/src/libANGLE/validationES2.cpp
gfx/angle/src/libANGLE/validationES2.h
gfx/angle/src/libANGLE/validationES3.cpp
gfx/angle/src/libANGLE/validationES3.h
gfx/angle/src/libANGLE/validationES_unittest.cpp
gfx/angle/src/libEGL.gypi
gfx/angle/src/libEGL/moz.build
gfx/angle/src/libGLESv2.gypi
gfx/angle/src/libGLESv2/entry_points_egl.cpp
gfx/angle/src/libGLESv2/entry_points_egl_ext.cpp
gfx/angle/src/libGLESv2/entry_points_gles_2_0.cpp
gfx/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp
gfx/angle/src/libGLESv2/entry_points_gles_2_0_ext.h
gfx/angle/src/libGLESv2/entry_points_gles_3_0.cpp
gfx/angle/src/libGLESv2/libGLESv2.cpp
gfx/angle/src/libGLESv2/libGLESv2.def
gfx/angle/src/libGLESv2/moz.build
gfx/angle/src/tests/BUILD.gn
gfx/angle/src/tests/angle_end2end_tests.gypi
gfx/angle/src/tests/angle_perftests.gypi
gfx/angle/src/tests/angle_unittests.gypi
gfx/angle/src/tests/compiler_tests/CollectVariables_test.cpp
gfx/angle/src/tests/compiler_tests/EXT_blend_func_extended_test.cpp
gfx/angle/src/tests/compiler_tests/FragDepth_test.cpp
gfx/angle/src/tests/compiler_tests/GLSLCompatibilityOutput_test.cpp
gfx/angle/src/tests/compiler_tests/MalformedShader_test.cpp
gfx/angle/src/tests/compiler_tests/ShCompile_test.cpp
gfx/angle/src/tests/compiler_tests/ShaderExtension_test.cpp
gfx/angle/src/tests/compiler_tests/ShaderVariable_test.cpp
gfx/angle/src/tests/compiler_tests/UnrollFlatten_test.cpp
gfx/angle/src/tests/deqp.gypi
gfx/angle/src/tests/deqp_support/angle_deqp_gtest.cpp
gfx/angle/src/tests/deqp_support/deqp_gles2_test_expectations.txt
gfx/angle/src/tests/deqp_support/deqp_gles3_test_expectations.txt
gfx/angle/src/tests/egl_tests/EGLPresentPathD3D11Test.cpp
gfx/angle/src/tests/egl_tests/EGLSurfaceTest.cpp
gfx/angle/src/tests/gl_tests/BlendMinMaxTest.cpp
gfx/angle/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
gfx/angle/src/tests/gl_tests/BufferDataTest.cpp
gfx/angle/src/tests/gl_tests/ClearTest.cpp
gfx/angle/src/tests/gl_tests/CompressedTextureTest.cpp
gfx/angle/src/tests/gl_tests/CopyTexImageTest.cpp
gfx/angle/src/tests/gl_tests/CubeMapTextureTest.cpp
gfx/angle/src/tests/gl_tests/DebugMarkerTest.cpp
gfx/angle/src/tests/gl_tests/DebugTest.cpp
gfx/angle/src/tests/gl_tests/DepthStencilFormatsTest.cpp
gfx/angle/src/tests/gl_tests/DiscardFramebufferEXTTest.cpp
gfx/angle/src/tests/gl_tests/DrawBuffersTest.cpp
gfx/angle/src/tests/gl_tests/DrawElementsTest.cpp
gfx/angle/src/tests/gl_tests/ETCTextureTest.cpp
gfx/angle/src/tests/gl_tests/FenceSyncTests.cpp
gfx/angle/src/tests/gl_tests/FramebufferFormatsTest.cpp
gfx/angle/src/tests/gl_tests/FramebufferRenderMipmapTest.cpp
gfx/angle/src/tests/gl_tests/GLSLTest.cpp
gfx/angle/src/tests/gl_tests/ImageTest.cpp
gfx/angle/src/tests/gl_tests/IncompleteTextureTest.cpp
gfx/angle/src/tests/gl_tests/IndexBufferOffsetTest.cpp
gfx/angle/src/tests/gl_tests/IndexedPointsTest.cpp
gfx/angle/src/tests/gl_tests/InstancingTest.cpp
gfx/angle/src/tests/gl_tests/LineLoopTest.cpp
gfx/angle/src/tests/gl_tests/MaxTextureSizeTest.cpp
gfx/angle/src/tests/gl_tests/MipmapTest.cpp
gfx/angle/src/tests/gl_tests/ObjectAllocationTest.cpp
gfx/angle/src/tests/gl_tests/OcclusionQueriesTest.cpp
gfx/angle/src/tests/gl_tests/PBOExtensionTest.cpp
gfx/angle/src/tests/gl_tests/PackUnpackTest.cpp
gfx/angle/src/tests/gl_tests/PbufferTest.cpp
gfx/angle/src/tests/gl_tests/PointSpritesTest.cpp
gfx/angle/src/tests/gl_tests/ProvokingVertexTest.cpp
gfx/angle/src/tests/gl_tests/ReadPixelsTest.cpp
gfx/angle/src/tests/gl_tests/RendererTest.cpp
gfx/angle/src/tests/gl_tests/SRGBTextureTest.cpp
gfx/angle/src/tests/gl_tests/SimpleOperationTest.cpp
gfx/angle/src/tests/gl_tests/SixteenBppTextureTest.cpp
gfx/angle/src/tests/gl_tests/StateChangeTest.cpp
gfx/angle/src/tests/gl_tests/SwizzleTest.cpp
gfx/angle/src/tests/gl_tests/TextureTest.cpp
gfx/angle/src/tests/gl_tests/TimerQueriesTest.cpp
gfx/angle/src/tests/gl_tests/TransformFeedbackTest.cpp
gfx/angle/src/tests/gl_tests/UniformBufferTest.cpp
gfx/angle/src/tests/gl_tests/UniformTest.cpp
gfx/angle/src/tests/gl_tests/UnpackAlignmentTest.cpp
gfx/angle/src/tests/gl_tests/UnpackRowLength.cpp
gfx/angle/src/tests/gl_tests/VertexAttributeTest.cpp
gfx/angle/src/tests/gl_tests/ViewportTest.cpp
gfx/angle/src/tests/perf_tests/ANGLEPerfTest.cpp
gfx/angle/src/tests/perf_tests/ANGLEPerfTest.h
gfx/angle/src/tests/perf_tests/BufferSubData.cpp
gfx/angle/src/tests/perf_tests/DrawCallPerf.cpp
gfx/angle/src/tests/perf_tests/EGLInitializePerf.cpp
gfx/angle/src/tests/perf_tests/IndexConversionPerf.cpp
gfx/angle/src/tests/perf_tests/IndexDataManagerTest.cpp
gfx/angle/src/tests/perf_tests/InstancingPerf.cpp
gfx/angle/src/tests/perf_tests/InterleavedAttributeData.cpp
gfx/angle/src/tests/perf_tests/PointSprites.cpp
gfx/angle/src/tests/perf_tests/TexSubImage.cpp
gfx/angle/src/tests/perf_tests/TextureSampling.cpp
gfx/angle/src/tests/test_utils/ANGLETest.cpp
gfx/angle/src/tests/test_utils/ANGLETest.h
gfx/angle/src/tests/test_utils/angle_test_configs.cpp
gfx/angle/src/tests/test_utils/angle_test_configs.h
--- a/dom/canvas/WebGLShaderValidator.cpp
+++ b/dom/canvas/WebGLShaderValidator.cpp
@@ -113,28 +113,28 @@ ShaderOutput(gl::GLContext* gl)
         case 430: return SH_GLSL_430_CORE_OUTPUT;
         case 440: return SH_GLSL_440_CORE_OUTPUT;
         case 450: return SH_GLSL_450_CORE_OUTPUT;
         default:
             MOZ_CRASH("Unexpected GLSL version.");
         }
     }
 
-    return SH_GLSL_OUTPUT;
+    return SH_GLSL_COMPATIBILITY_OUTPUT;
 }
 
 webgl::ShaderValidator*
 WebGLContext::CreateShaderValidator(GLenum shaderType) const
 {
     if (mBypassShaderValidation)
         return nullptr;
 
     ShShaderSpec spec = IsWebGL2() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
     ShShaderOutput outputLanguage = gl->IsGLES() ? SH_ESSL_OUTPUT
-                                                 : SH_GLSL_OUTPUT;
+                                                 : SH_GLSL_COMPATIBILITY_OUTPUT;
 
     // If we're using WebGL2 we want a more specific version of GLSL
     if (IsWebGL2())
         outputLanguage = ShaderOutput(gl);
 
     ShBuiltInResources resources;
     memset(&resources, 0, sizeof(resources));
     ShInitBuiltInResources(&resources);
--- a/dom/canvas/test/webgl-mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest.ini
@@ -10,17 +10,17 @@ support-files =
 
 [webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html]
 fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6')
 [webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html]
 fail-if = (os == 'android')
 [webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html]
 fail-if = (os == 'android')
 [webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html]
-fail-if = (os == 'android') || (os == 'mac') || (os == 'win')
+fail-if = (os == 'android') || (os == 'mac') || (os == 'win' && os_version == '6.1')
 [webgl-mochitest/ensure-exts/test_EXT_frag_depth.html]
 fail-if = (os == 'android')
 [webgl-mochitest/ensure-exts/test_EXT_sRGB.html]
 fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6') || (os == 'win')
 [webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html]
 fail-if = (os == 'android') || (os == 'linux') || (os == 'mac')
 [webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html]
 fail-if = (os == 'android') || (os == 'linux')
--- a/gfx/angle/BUILD.gn
+++ b/gfx/angle/BUILD.gn
@@ -10,64 +10,59 @@ angle_git_is_present = exec_script("src/
                                    [
                                      "check",
                                      rebase_path(".", root_build_dir),
                                    ],
                                    "value")
 
 angle_use_commit_id = angle_git_is_present == 1
 
-gles_gypi = exec_script(
-  "//build/gypi_to_gn.py",
-  [ rebase_path("src/libGLESv2.gypi") ],
-  "scope",
-  [ "src/libGLESv2.gypi" ])
+gles_gypi = exec_script("//build/gypi_to_gn.py",
+                        [ rebase_path("src/libGLESv2.gypi") ],
+                        "scope",
+                        [ "src/libGLESv2.gypi" ])
 
-compiler_gypi = exec_script(
-  "//build/gypi_to_gn.py",
-  [ rebase_path("src/compiler.gypi") ],
-  "scope",
-  [ "src/compiler.gypi" ])
+compiler_gypi = exec_script("//build/gypi_to_gn.py",
+                            [ rebase_path("src/compiler.gypi") ],
+                            "scope",
+                            [ "src/compiler.gypi" ])
 
 # This config is exported to dependent targets (and also applied to internal
 # ones).
 config("external_config") {
-  include_dirs = [
-    "include",
-  ]
+  include_dirs = [ "include" ]
 }
 
 # This config is applied to internal Angle targets (not pushed to dependents).
 config("internal_config") {
   include_dirs = [
     "include",
     "src",
   ]
 }
 
 if (is_win) {
   copy("copy_compiler_dll") {
-    sources = [ "$windows_sdk_path/Redist/D3D/$target_cpu/d3dcompiler_47.dll" ]
-    outputs = [ "$root_build_dir/d3dcompiler_47.dll" ]
+    sources = [
+      "$windows_sdk_path/Redist/D3D/$target_cpu/d3dcompiler_47.dll",
+    ]
+    outputs = [
+      "$root_out_dir/d3dcompiler_47.dll",
+    ]
   }
 }
 
 component("translator") {
   sources = [
     "src/compiler/translator/ShaderLang.cpp",
     "src/compiler/translator/ShaderVars.cpp",
   ]
 
   defines = [ "ANGLE_TRANSLATOR_IMPLEMENTATION" ]
 
-  if (angle_enable_hlsl) {
-    sources += rebase_path(compiler_gypi.angle_translator_lib_hlsl_sources, ".", "src")
-    defines += [ "ANGLE_ENABLE_HLSL" ]
-  }
-
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     "//build/config/compiler:no_chromium_code",
   ]
 
   public_deps = [
     ":translator_lib",
@@ -79,19 +74,19 @@ source_set("includes") {
   sources = [
     "include/EGL/egl.h",
     "include/EGL/eglext.h",
     "include/EGL/eglplatform.h",
     "include/GLES2/gl2.h",
     "include/GLES2/gl2ext.h",
     "include/GLES2/gl2platform.h",
     "include/GLES3/gl3.h",
-    "include/GLES3/gl3platform.h",
     "include/GLES3/gl31.h",
     "include/GLES3/gl32.h",
+    "include/GLES3/gl3platform.h",
     "include/GLSLANG/ShaderLang.h",
     "include/KHR/khrplatform.h",
   ]
 }
 
 static_library("preprocessor") {
   sources = rebase_path(compiler_gypi.angle_preprocessor_sources, ".", "src")
 
@@ -101,42 +96,53 @@ static_library("preprocessor") {
     "//build/config/compiler:no_chromium_code",
   ]
 }
 
 config("translator_static_config") {
   defines = [ "ANGLE_TRANSLATOR_STATIC" ]
 }
 
-
 config("debug_annotations_config") {
   if (is_debug) {
-    defines = [
-      "ANGLE_ENABLE_DEBUG_ANNOTATIONS",
-    ]
+    defines = [ "ANGLE_ENABLE_DEBUG_ANNOTATIONS" ]
   }
 }
 
 static_library("angle_common") {
   sources = rebase_path(gles_gypi.libangle_common_sources, ".", "src")
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     ":debug_annotations_config",
     "//build/config/compiler:no_chromium_code",
   ]
 }
 
 static_library("translator_lib") {
   sources = rebase_path(compiler_gypi.angle_translator_lib_sources, ".", "src")
+  defines = []
+
+  if (angle_enable_essl) {
+    sources +=
+        rebase_path(compiler_gypi.angle_translator_lib_essl_sources, ".", "src")
+    defines += [ "ANGLE_ENABLE_ESSL" ]
+  }
+
+  if (angle_enable_glsl) {
+    sources +=
+        rebase_path(compiler_gypi.angle_translator_lib_glsl_sources, ".", "src")
+    defines += [ "ANGLE_ENABLE_GLSL" ]
+  }
 
   if (angle_enable_hlsl) {
-    sources += rebase_path(compiler_gypi.angle_translator_lib_hlsl_sources, ".", "src")
-    defines = [ "ANGLE_ENABLE_HLSL" ]
+    sources +=
+        rebase_path(compiler_gypi.angle_translator_lib_hlsl_sources, ".", "src")
+    defines += [ "ANGLE_ENABLE_HLSL" ]
   }
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     ":translator_static_config",
     "//build/config/compiler:no_chromium_code",
   ]
   public_configs = [ ":external_config" ]
@@ -241,28 +247,23 @@ config("libANGLE_config") {
   }
 }
 
 static_library("libANGLE") {
   sources = rebase_path(gles_gypi.libangle_sources, ".", "src")
 
   include_dirs = []
   libs = []
-  defines = [
-    "LIBANGLE_IMPLEMENTATION",
-  ]
+  defines = [ "LIBANGLE_IMPLEMENTATION" ]
 
   # Shared D3D sources.
   if (angle_enable_d3d9 || angle_enable_d3d11) {
     sources += rebase_path(gles_gypi.libangle_d3d_shared_sources, ".", "src")
 
-    defines += [
-      "ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ " +
-        "\"d3dcompiler_47.dll\", \"d3dcompiler_46.dll\", \"d3dcompiler_43.dll\" }",
-    ]
+    defines += [ "ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ " + "\"d3dcompiler_47.dll\", \"d3dcompiler_46.dll\", \"d3dcompiler_43.dll\" }" ]
   }
 
   if (angle_enable_d3d9) {
     sources += rebase_path(gles_gypi.libangle_d3d9_sources, ".", "src")
     libs += [ "d3d9.lib" ]
   }
 
   if (angle_enable_d3d11) {
@@ -280,101 +281,100 @@ static_library("libANGLE") {
     }
     if (use_x11) {
       sources += rebase_path(gles_gypi.libangle_gl_glx_sources, ".", "src")
       libs += [ "X11" ]
     }
   }
 
   if (is_debug) {
-    defines += [
-      "ANGLE_GENERATE_SHADER_DEBUG_INFO",
-    ]
+    defines += [ "ANGLE_GENERATE_SHADER_DEBUG_INFO" ]
   }
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":commit_id_config",
     ":debug_annotations_config",
     ":libANGLE_config",
     ":internal_config",
     "//build/config/compiler:no_chromium_code",
   ]
 
   deps = [
+    ":angle_common",
     ":commit_id",
     ":includes",
     ":translator_static",
-    ":angle_common",
   ]
 
   if (is_win) {
     deps += [ ":copy_compiler_dll" ]
   }
 }
 
 shared_library("libGLESv2") {
   sources = rebase_path(gles_gypi.libglesv2_sources, ".", "src")
 
   if (is_win) {
-    ldflags = [ "/DEF:" +
-                rebase_path("src/libGLESv2/libGLESv2.def", root_build_dir) ]
+    ldflags =
+        [ "/DEF:" + rebase_path("src/libGLESv2/libGLESv2.def", root_build_dir) ]
   }
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     ":commit_id_config",
     ":debug_annotations_config",
     ":libANGLE_config",
     "//build/config/compiler:no_chromium_code",
   ]
 
-  defines = [
-    "LIBGLESV2_IMPLEMENTATION",
-  ]
+  defines = [ "LIBGLESV2_IMPLEMENTATION" ]
 
   deps = [
     ":includes",
     ":libANGLE",
   ]
 }
 
 shared_library("libEGL") {
   sources = rebase_path(gles_gypi.libegl_sources, ".", "src")
 
   if (is_win) {
-    ldflags = [ "/DEF:" +
-                rebase_path("src/libEGL/libEGL.def", root_build_dir) ]
+    ldflags = [ "/DEF:" + rebase_path("src/libEGL/libEGL.def", root_build_dir) ]
   }
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     ":commit_id_config",
     ":debug_annotations_config",
     ":libANGLE_config",
     "//build/config/compiler:no_chromium_code",
   ]
 
-  defines = [
-    "LIBEGL_IMPLEMENTATION",
-  ]
+  defines = [ "LIBEGL_IMPLEMENTATION" ]
 
   deps = [
     ":includes",
     ":libGLESv2",
   ]
 }
 
-util_gypi = exec_script(
-  "//build/gypi_to_gn.py",
-  [ rebase_path("util/util.gyp") ],
-  "scope",
-  [ "util/util.gyp" ])
+util_gypi = exec_script("//build/gypi_to_gn.py",
+                        [ rebase_path("util/util.gyp") ],
+                        "scope",
+                        [ "util/util.gyp" ])
+
+config("angle_util_config") {
+  include_dirs = [ "util" ]
+  if (is_linux) {
+    libs = [ "X11" ]
+  }
+}
 
 static_library("angle_util") {
   sources = rebase_path(util_gypi.util_sources, ".", "util")
 
   if (is_win) {
     sources += rebase_path(util_gypi.util_win32_sources, ".", "util")
   }
 
@@ -391,22 +391,21 @@ static_library("angle_util") {
     sources += rebase_path(util_gypi.util_x11_sources, ".", "util")
   }
 
   defines = [
     "GL_GLEXT_PROTOTYPES",
     "EGL_EGLEXT_PROTOTYPES",
   ]
 
-  configs += [
+  configs += [ ":debug_annotations_config" ]
+
+  public_configs = [
+    ":angle_util_config",
     ":internal_config",
-    ":debug_annotations_config",
-  ]
-
-  include_dirs = [
-    "util",
   ]
 
   deps = [
+    ":angle_common",
     ":libEGL",
     ":libGLESv2",
   ]
 }
--- a/gfx/angle/DEPS
+++ b/gfx/angle/DEPS
@@ -61,14 +61,48 @@ hooks = [
     'action': [ 'download_from_google_storage',
                 '--no_resume',
                 '--platform=linux*',
                 '--no_auth',
                 '--bucket', 'chromium-clang-format',
                 '-s', 'buildtools/linux64/clang-format.sha1',
     ],
   },
+  # Pull GN binaries using checked-in hashes.
+  {
+    'name': 'gn_win',
+    'pattern': '.',
+    'action': [ 'download_from_google_storage',
+                '--no_resume',
+                '--platform=win32',
+                '--no_auth',
+                '--bucket', 'chromium-gn',
+                '-s', 'buildtools/win/gn.exe.sha1',
+    ],
+  },
+  {
+    'name': 'gn_mac',
+    'pattern': '.',
+    'action': [ 'download_from_google_storage',
+                '--no_resume',
+                '--platform=darwin',
+                '--no_auth',
+                '--bucket', 'chromium-gn',
+                '-s', 'buildtools/mac/gn.sha1',
+    ],
+  },
+  {
+    'name': 'gn_linux64',
+    'pattern': '.',
+    'action': [ 'download_from_google_storage',
+                '--no_resume',
+                '--platform=linux*',
+                '--no_auth',
+                '--bucket', 'chromium-gn',
+                '-s', 'buildtools/linux64/gn.sha1',
+    ],
+  },
   {
     # A change to a .gyp, .gypi, or to GYP itself should run the generator.
     "pattern": ".",
     "action": ["python", "build/gyp_angle"],
   },
 ]
--- a/gfx/angle/README.md
+++ b/gfx/angle/README.md
@@ -34,10 +34,11 @@ View the [Dev setup instructions](doc/De
 * Become a [code contributor](doc/ContributingCode.md).
 * Refer to ANGLE's [coding standard](doc/CodingStandard.md).
 * Learn how to [build ANGLE for Chromium development](doc/BuildingAngleForChromiumDevelopment.md).
 * [Choose an ANGLE branch](doc/ChoosingANGLEBranch.md) to track in your own project.
 * File bugs in the [issue tracker](http://code.google.com/p/angleproject/issues/list) (preferably with an isolated test-case).
 * Read about WebGL on the [Khronos WebGL Wiki](http://khronos.org/webgl/wiki/Main_Page).
 * Learn about implementation details in the [OpenGL Insights chapter on ANGLE](http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-ANGLE.pdf) and this [ANGLE presentation](https://drive.google.com/file/d/0Bw29oYeC09QbbHoxNE5EUFh0RGs/view?usp=sharing).
 * Learn about the past, present, and future of the ANGLE implementation in [this recent presentation](https://docs.google.com/presentation/d/1CucIsdGVDmdTWRUbg68IxLE5jXwCb2y1E9YVhQo0thg/pub?start=false&loop=false).
+* Notes on [debugging ANGLE](doc/DebuggingTips.md).
 * If you use ANGLE in your own project, we'd love to hear about it!
 
--- a/gfx/angle/include/EGL/eglext.h
+++ b/gfx/angle/include/EGL/eglext.h
@@ -463,16 +463,21 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySu
 #define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
 #define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
 #endif /* EGL_ANGLE_direct3d_display */
 
 #ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
 #define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
 #endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
 
+#ifndef EGL_ANGLE_direct_composition
+#define EGL_ANGLE_direct_composition 1
+#define EGL_DIRECT_COMPOSITION_ANGLE 0x33A5
+#endif /* EGL_ANGLE_direct_composition */
+
 #ifndef EGL_ANGLE_platform_angle
 #define EGL_ANGLE_platform_angle 1
 #define EGL_PLATFORM_ANGLE_ANGLE          0x3202
 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE     0x3203
 #define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
 #define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
 #define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
 #endif /* EGL_ANGLE_platform_angle */
@@ -499,16 +504,36 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySu
 #define EGL_FIXED_SIZE_ANGLE              0x3201
 #endif /* EGL_ANGLE_window_fixed_size */
 
 #ifndef EGL_ANGLE_x11_visual
 #define EGL_ANGLE_x11_visual
 #define EGL_X11_VISUAL_ID_ANGLE 0x33A3
 #endif /* EGL_ANGLE_x11_visual */
 
+#ifndef EGL_ANGLE_flexible_surface_compatibility
+#define EGL_ANGLE_flexible_surface_compatibility 1
+#define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
+#endif /* EGL_ANGLE_flexible_surface_compatibility */
+
+#ifndef EGL_ANGLE_surface_orientation
+#define EGL_ANGLE_surface_orientation
+#define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7
+#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
+#define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001
+#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
+#endif /* EGL_ANGLE_surface_orientation */
+
+#ifndef EGL_ANGLE_experimental_present_path
+#define EGL_ANGLE_experimental_present_path
+#define EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE 0x33A4
+#define EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE 0x33A9
+#define EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE 0x33AA
+#endif /* EGL_ANGLE_experimental_present_path */
+
 #ifndef EGL_ARM_pixmap_multisample_discard
 #define EGL_ARM_pixmap_multisample_discard 1
 #define EGL_DISCARD_SAMPLES_ARM           0x3286
 #endif /* EGL_ARM_pixmap_multisample_discard */
 
 #ifndef EGL_EXT_buffer_age
 #define EGL_EXT_buffer_age 1
 #define EGL_BUFFER_AGE_EXT                0x313D
--- a/gfx/angle/include/GLES2/gl2ext.h
+++ b/gfx/angle/include/GLES2/gl2ext.h
@@ -2915,13 +2915,28 @@ GL_APICALL void GL_APIENTRY glEndTilingQ
 #define GL_WRITEONLY_RENDERING_QCOM       0x8823
 #endif /* GL_QCOM_writeonly_rendering */
 
 #ifndef GL_VIV_shader_binary
 #define GL_VIV_shader_binary 1
 #define GL_SHADER_BINARY_VIV              0x8FC4
 #endif /* GL_VIV_shader_binary */
 
+#ifndef GL_ANGLE_lossy_etc_decode
+#define GL_ANGLE_lossy_etc_decode 1
+#define GL_ETC1_RGB8_LOSSY_DECODE_ANGLE                                  0x9690
+#define GL_COMPRESSED_R11_LOSSY_DECODE_EAC_ANGLE                         0x9691
+#define GL_COMPRESSED_SIGNED_R11_LOSSY_DECODE_EAC_ANGLE                  0x9692
+#define GL_COMPRESSED_RG11_LOSSY_DECODE_EAC_ANGLE                        0x9693
+#define GL_COMPRESSED_SIGNED_RG11_LOSSY_DECODE_EAC_ANGLE                 0x9694
+#define GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE                       0x9695
+#define GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE                      0x9696
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE   0x9697
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE  0x9698
+#define GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE                  0x9699
+#define GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE           0x969A
+#endif /* GL_ANGLE_lossy_etc_decode */
+
 #ifdef __cplusplus
 }
 #endif
 
 #endif
--- a/gfx/angle/include/GLSLANG/ShaderLang.h
+++ b/gfx/angle/include/GLSLANG/ShaderLang.h
@@ -43,17 +43,17 @@ typedef unsigned int GLenum;
 }
 
 // Must be included after GLenum proxy typedef
 // Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
 #include "ShaderVars.h"
 
 // Version number for shader translation API.
 // It is incremented every time the API changes.
-#define ANGLE_SH_VERSION 140
+#define ANGLE_SH_VERSION 143
 
 typedef enum {
   SH_GLES2_SPEC = 0x8B40,
   SH_WEBGL_SPEC = 0x8B41,
 
   SH_GLES3_SPEC = 0x8B86,
   SH_WEBGL2_SPEC = 0x8B87,
 
@@ -75,40 +75,45 @@ typedef enum {
   // This new main function will call the css_main function.
   // It may also perform additional operations like varying assignment, texture
   // access, and gl_FragColor assignment in order to implement the CSS Shaders
   // blend modes.
   //
   SH_CSS_SHADERS_SPEC = 0x8B42
 } ShShaderSpec;
 
-typedef enum {
-  SH_ESSL_OUTPUT               = 0x8B45,
-  // SH_GLSL_OUTPUT is deprecated. This is to not break the build.
-  SH_GLSL_OUTPUT               = 0x8B46,
-  SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
-  // SH_GLSL_CORE_OUTPUT is deprecated.
-  SH_GLSL_CORE_OUTPUT          = 0x8B47,
-  //Note: GL introduced core profiles in 1.5. However, for compatiblity with Chromium, we treat SH_GLSL_CORE_OUTPUT as GLSL_130_OUTPUT.
-  //TODO: Remove SH_GLSL_CORE_OUTPUT
-  SH_GLSL_130_OUTPUT           = 0x8B47,
-  SH_GLSL_140_OUTPUT           = 0x8B80,
-  SH_GLSL_150_CORE_OUTPUT      = 0x8B81,
-  SH_GLSL_330_CORE_OUTPUT      = 0x8B82,
-  SH_GLSL_400_CORE_OUTPUT      = 0x8B83,
-  SH_GLSL_410_CORE_OUTPUT      = 0x8B84,
-  SH_GLSL_420_CORE_OUTPUT      = 0x8B85,
-  SH_GLSL_430_CORE_OUTPUT      = 0x8B86,
-  SH_GLSL_440_CORE_OUTPUT      = 0x8B87,
-  SH_GLSL_450_CORE_OUTPUT      = 0x8B88,
+typedef enum
+{
+    // ESSL output only supported in some configurations.
+    SH_ESSL_OUTPUT = 0x8B45,
 
-  // HLSL output only supported in some configurations.
-  SH_HLSL_OUTPUT   = 0x8B48,
-  SH_HLSL9_OUTPUT  = 0x8B48,
-  SH_HLSL11_OUTPUT = 0x8B49
+    // GLSL output only supported in some configurations.
+    SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
+    // Note: GL introduced core profiles in 1.5.
+    SH_GLSL_130_OUTPUT      = 0x8B47,
+    SH_GLSL_140_OUTPUT      = 0x8B80,
+    SH_GLSL_150_CORE_OUTPUT = 0x8B81,
+    SH_GLSL_330_CORE_OUTPUT = 0x8B82,
+    SH_GLSL_400_CORE_OUTPUT = 0x8B83,
+    SH_GLSL_410_CORE_OUTPUT = 0x8B84,
+    SH_GLSL_420_CORE_OUTPUT = 0x8B85,
+    SH_GLSL_430_CORE_OUTPUT = 0x8B86,
+    SH_GLSL_440_CORE_OUTPUT = 0x8B87,
+    SH_GLSL_450_CORE_OUTPUT = 0x8B88,
+
+    // HLSL output only supported in some configurations.
+    // Deprecated:
+    SH_HLSL_OUTPUT   = 0x8B48,
+    SH_HLSL9_OUTPUT  = 0x8B48,
+    SH_HLSL11_OUTPUT = 0x8B49,
+
+    // Prefer using these to specify HLSL output type:
+    SH_HLSL_3_0_OUTPUT       = 0x8B48,  // D3D 9
+    SH_HLSL_4_1_OUTPUT       = 0x8B49,  // D3D 11
+    SH_HLSL_4_0_FL9_3_OUTPUT = 0x8B4A   // D3D 11 feature level 9_3
 } ShShaderOutput;
 
 // Compile options.
 typedef enum {
   SH_VALIDATE                = 0,
   SH_VALIDATE_LOOP_INDEXING  = 0x0001,
   SH_INTERMEDIATE_TREE       = 0x0002,
   SH_OBJECT_CODE             = 0x0004,
@@ -329,19 +334,19 @@ COMPILER_EXPORT const std::string &ShGet
 // Driver calls these to create and destroy compiler objects.
 //
 // Returns the handle of constructed compiler, null if the requested compiler is
 // not supported.
 // Parameters:
 // type: Specifies the type of shader - GL_FRAGMENT_SHADER or GL_VERTEX_SHADER.
 // spec: Specifies the language spec the compiler must conform to -
 //       SH_GLES2_SPEC or SH_WEBGL_SPEC.
-// output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
-//         SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. Note: HLSL output is only
-//         supported in some configurations.
+// output: Specifies the output code type - for example SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
+//         SH_HLSL_3_0_OUTPUT or SH_HLSL_4_1_OUTPUT. Note: Each output type may only
+//         be supported in some configurations.
 // resources: Specifies the built-in resources.
 COMPILER_EXPORT ShHandle ShConstructCompiler(
     sh::GLenum type,
     ShShaderSpec spec,
     ShShaderOutput output,
     const ShBuiltInResources *resources);
 COMPILER_EXPORT void ShDestruct(ShHandle handle);
 
--- a/gfx/angle/include/GLSLANG/ShaderVars.h
+++ b/gfx/angle/include/GLSLANG/ShaderVars.h
@@ -195,21 +195,24 @@ struct COMPILER_EXPORT Varying : public 
 
 struct COMPILER_EXPORT InterfaceBlock
 {
     InterfaceBlock();
     ~InterfaceBlock();
     InterfaceBlock(const InterfaceBlock &other);
     InterfaceBlock &operator=(const InterfaceBlock &other);
 
+    // Fields from blocks with non-empty instance names are prefixed with the block name.
+    std::string fieldPrefix() const;
+
     std::string name;
     std::string mappedName;
     std::string instanceName;
     unsigned int arraySize;
     BlockLayoutType layout;
     bool isRowMajorLayout;
     bool staticUse;
     std::vector<InterfaceBlockField> fields;
 };
 
-}
+}  // namespace sh
 
 #endif // GLSLANG_SHADERVARS_H_
--- a/gfx/angle/moz.build
+++ b/gfx/angle/moz.build
@@ -103,34 +103,35 @@ UNIFIED_SOURCES += [
     'src/compiler/translator/VersionGLSL.cpp',
     'src/third_party/compiler/ArrayBoundsClamper.cpp',
 ]
 SOURCES += [
     'src/compiler/translator/glslang_lex.cpp',
     'src/compiler/translator/glslang_tab.cpp',
 ]
 
-if CONFIG['GNU_CXX'] or CONFIG['CLANG_CL']:
+
+if CONFIG['GNU_CXX']:
     CXXFLAGS += [
         '-Wno-attributes',
         '-Wno-shadow',
         '-Wno-sign-compare',
         '-Wno-unknown-pragmas',
         '-Wno-unreachable-code',
     ]
-if CONFIG['GNU_CXX'] and not CONFIG['CLANG_CXX'] and not CONFIG['CLANG_CL']:
-    CXXFLAGS += [
-        '-Wno-shadow-compatible-local',
-        '-Wno-shadow-local',
-    ]
-if CONFIG['CLANG_CXX'] or CONFIG['CLANG_CL']:
-    CXXFLAGS += [
-        '-Wno-inconsistent-missing-override',
-        '-Wno-unused-private-field',
-    ]
+    if CONFIG['CLANG_CXX']:
+        CXXFLAGS += [
+            '-Wno-inconsistent-missing-override',
+            '-Wno-unused-private-field',
+        ]
+    else:
+        CXXFLAGS += [
+            '-Wno-shadow-compatible-local',
+            '-Wno-shadow-local',
+        ]
 
 if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
     LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
 
 DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
 DEFINES['_HAS_EXCEPTIONS'] = 0
 
 if not CONFIG['MOZ_DEBUG']:
@@ -149,16 +150,18 @@ DEFINES['GL_GLEXT_PROTOTYPES'] = ""
 DEFINES['EGLAPI'] = ""
 
 
 # Only build libEGL/libGLESv2 on Windows
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     DIRS += [ 'src/libANGLE', 'src/libGLESv2', 'src/libEGL' ]
 
 DEFINES['ANGLE_ENABLE_HLSL'] = "1"
+DEFINES['ANGLE_ENABLE_GLSL'] = "1"
+DEFINES['ANGLE_ENABLE_ESSL'] = "1"
 DEFINES['ANGLE_ENABLE_KEYEDMUTEX'] = "1"
 
 EXPORTS.angle += [ 'include/GLSLANG/ShaderLang.h', 'include/GLSLANG/ShaderVars.h' ]
 EXPORTS.angle.KHR += [ 'include/KHR/khrplatform.h' ]
 
 LOCAL_INCLUDES += [ 'include', 'src' ]
 
 # We allow warnings for third-party code that can be updated from upstream.
--- a/gfx/angle/src/angle.gyp
+++ b/gfx/angle/src/angle.gyp
@@ -11,16 +11,18 @@
         'angle_id_script_base': 'commit_id.py',
         'angle_id_script': '<(angle_gen_path)/<(angle_id_script_base)',
         'angle_id_header_base': 'commit.h',
         'angle_id_header': '<(angle_gen_path)/id/<(angle_id_header_base)',
         'angle_use_commit_id%': '<!(python <(angle_id_script_base) check ..)',
         'angle_enable_d3d9%': 0,
         'angle_enable_d3d11%': 0,
         'angle_enable_gl%': 0,
+        'angle_enable_essl%': 1, # Enable this for all configs by default
+        'angle_enable_glsl%': 1, # Enable this for all configs by default
         'angle_enable_hlsl%': 0,
         'angle_link_glx%': 0,
         'angle_gl_library_type%': 'shared_library',
         'conditions':
         [
             ['OS=="win"',
             {
                 'angle_enable_gl%': 1,
--- a/gfx/angle/src/commit.h
+++ b/gfx/angle/src/commit.h
@@ -1,3 +1,3 @@
-#define ANGLE_COMMIT_HASH "d00f803db3a2"
+#define ANGLE_COMMIT_HASH "f1101625dbbe"
 #define ANGLE_COMMIT_HASH_SIZE 12
-#define ANGLE_COMMIT_DATE "2015-12-15 23:09:49 -0500"
+#define ANGLE_COMMIT_DATE "2016-02-24 21:04:03 -0500"
--- a/gfx/angle/src/common/BitSetIterator_unittest.cpp
+++ b/gfx/angle/src/common/BitSetIterator_unittest.cpp
@@ -50,17 +50,17 @@ TEST_F(BitSetIteratorTest, Iterator)
 TEST_F(BitSetIteratorTest, EmptySet)
 {
     // We don't use the FAIL gtest macro here since it returns immediately,
     // causing an unreachable code warning in MSVS
     bool sawBit = false;
     for (unsigned long bit : IterateBitSet(mStateBits))
     {
         sawBit = true;
-        UNUSED_TRACE_VARIABLE(bit);
+        UNUSED_VARIABLE(bit);
     }
     EXPECT_FALSE(sawBit);
 }
 
 // Test iterating a result of combining two bitsets.
 TEST_F(BitSetIteratorTest, NonLValueBitset)
 {
     std::bitset<40> otherBits;
--- a/gfx/angle/src/common/Optional.h
+++ b/gfx/angle/src/common/Optional.h
@@ -37,16 +37,23 @@ struct Optional
 
     Optional &operator=(const T &value)
     {
         mValue = value;
         mValid = true;
         return *this;
     }
 
+    Optional &operator=(T &&value)
+    {
+        mValue = std::move(value);
+        mValid = true;
+        return *this;
+    }
+
     void reset()
     {
         mValid = false;
     }
 
     static Optional Invalid() { return Optional(); }
 
     bool valid() const { return mValid; }
--- a/gfx/angle/src/common/angleutils.cpp
+++ b/gfx/angle/src/common/angleutils.cpp
@@ -3,18 +3,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #include "common/angleutils.h"
 #include "common/debug.h"
 
 #include <stdio.h>
+
+#include <limits>
 #include <vector>
 
+namespace angle
+{
+const uintptr_t DirtyPointer = std::numeric_limits<uintptr_t>::max();
+}
+
 size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& outBuffer)
 {
     // Attempt to just print to the current buffer
     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);
--- a/gfx/angle/src/common/angleutils.h
+++ b/gfx/angle/src/common/angleutils.h
@@ -28,16 +28,17 @@ class NonCopyable
   public:
     NonCopyable() = default;
     ~NonCopyable() = default;
   protected:
     NonCopyable(const NonCopyable&) = delete;
     void operator=(const NonCopyable&) = delete;
 };
 
+extern const uintptr_t DirtyPointer;
 }
 
 template <typename T, size_t N>
 inline size_t ArraySize(T(&)[N])
 {
     return N;
 }
 
--- a/gfx/angle/src/common/debug.cpp
+++ b/gfx/angle/src/common/debug.cpp
@@ -48,17 +48,17 @@ void output(bool traceInDebugOnly, Messa
             break;
           case DebugTraceOutputTypeSetMarker:
             g_debugAnnotator->setMarker(formattedWideMessage.c_str());
             break;
         }
     }
 
     std::string formattedMessage;
-    UNUSED_TRACE_VARIABLE(formattedMessage);
+    UNUSED_VARIABLE(formattedMessage);
 
 #if !defined(NDEBUG) && defined(_MSC_VER)
     if (messageType == MESSAGE_ERR)
     {
         if (formattedMessage.empty())
         {
             formattedMessage = FormatString(format, vararg);
         }
--- a/gfx/angle/src/common/debug.h
+++ b/gfx/angle/src/common/debug.h
@@ -11,17 +11,17 @@
 
 #include <assert.h>
 #include <stdio.h>
 #include <string>
 
 #include "common/angleutils.h"
 
 #if !defined(TRACE_OUTPUT_FILE)
-#define TRACE_OUTPUT_FILE "debug.txt"
+#define TRACE_OUTPUT_FILE "angle_debug.txt"
 #endif
 
 namespace gl
 {
 
 enum MessageType
 {
     MESSAGE_TRACE,
@@ -86,17 +86,17 @@ bool DebugAnnotationsActive();
 #define ERR(message, ...) (void(0))
 #endif
 
 // A macro to log a performance event around a scope.
 #if defined(ANGLE_TRACE_ENABLED)
 #if defined(_MSC_VER)
 #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__);
 #else
-#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper(message "\n", ##__VA_ARGS__);
+#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper("%s" message "\n", __FUNCTION__, ##__VA_ARGS__);
 #endif // _MSC_VER
 #else
 #define EVENT(message, ...) (void(0))
 #endif
 
 #if defined(ANGLE_TRACE_ENABLED)
 #undef ANGLE_TRACE_ENABLED
 #endif
@@ -109,21 +109,17 @@ bool DebugAnnotationsActive();
         assert(expression); \
     } ANGLE_EMPTY_STATEMENT
 #define UNUSED_ASSERTION_VARIABLE(variable)
 #else
 #define ASSERT(expression) (void(0))
 #define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable)
 #endif
 
-#ifndef ANGLE_ENABLE_DEBUG_TRACE
-#define UNUSED_TRACE_VARIABLE(variable) ((void)variable)
-#else
-#define UNUSED_TRACE_VARIABLE(variable)
-#endif
+#define UNUSED_VARIABLE(variable) ((void)variable)
 
 // A macro to indicate unimplemented functionality
 
 #if defined (ANGLE_TEST_CONFIG)
 #define NOASSERT_UNIMPLEMENTED 1
 #endif
 
 // Define NOASSERT_UNIMPLEMENTED to non zero to skip the assert fail in the unimplemented checks
--- a/gfx/angle/src/common/mathutil.h
+++ b/gfx/angle/src/common/mathutil.h
@@ -488,19 +488,20 @@ inline signed short average(signed short
     return ((int)a + (int)b) / 2;
 }
 
 inline unsigned int average(unsigned int a, unsigned int b)
 {
     return ((a ^ b) >> 1) + (a & b);
 }
 
-inline signed int average(signed int a, signed int b)
+inline int average(int a, int b)
 {
-    return ((long long)a + (long long)b) / 2;
+    long long average = (static_cast<long long>(a) + static_cast<long long>(b)) / 2ll;
+    return static_cast<int>(average);
 }
 
 inline float average(float a, float b)
 {
     return (a + b) * 0.5f;
 }
 
 inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
@@ -579,19 +580,20 @@ struct IndexRange
 // First, both normalized floating-point values are converted into 16-bit integer values.
 // Then, the results are packed into the returned 32-bit unsigned integer.
 // The first float value will be written to the least significant bits of the output;
 // the last float value will be written to the most significant bits.
 // The conversion of each value to fixed point is done as follows :
 // packSnorm2x16 : round(clamp(c, -1, +1) * 32767.0)
 inline uint32_t packSnorm2x16(float f1, float f2)
 {
-    uint16_t leastSignificantBits = static_cast<uint16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
-    uint16_t mostSignificantBits = static_cast<uint16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
-    return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
+    int16_t leastSignificantBits = static_cast<int16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
+    int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
+    return static_cast<uint32_t>(mostSignificantBits) << 16 |
+           (static_cast<uint32_t>(leastSignificantBits) & 0xFFFF);
 }
 
 // First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
 // component is converted to a normalized floating-point value to generate the returned two float values.
 // The first float value will be extracted from the least significant bits of the input;
 // the last float value will be extracted from the most-significant bits.
 // The conversion for unpacked fixed-point value to floating point is done as follows:
 // unpackSnorm2x16 : clamp(f / 32767.0, -1, +1)
--- a/gfx/angle/src/compiler.gypi
+++ b/gfx/angle/src/compiler.gypi
@@ -20,36 +20,32 @@
             '../include/GLES3/gl32.h',
             '../include/GLSLANG/ShaderLang.h',
             '../include/GLSLANG/ShaderVars.h',
             '../include/KHR/khrplatform.h',
             '../include/angle_gl.h',
             'compiler/translator/BaseTypes.h',
             'compiler/translator/BuiltInFunctionEmulator.cpp',
             'compiler/translator/BuiltInFunctionEmulator.h',
-            'compiler/translator/BuiltInFunctionEmulatorGLSL.cpp',
-            'compiler/translator/BuiltInFunctionEmulatorGLSL.h',
             'compiler/translator/Cache.cpp',
             'compiler/translator/Cache.h',
             'compiler/translator/CallDAG.cpp',
             'compiler/translator/CallDAG.h',
             'compiler/translator/CodeGen.cpp',
             'compiler/translator/Common.h',
             'compiler/translator/Compiler.cpp',
             'compiler/translator/Compiler.h',
             'compiler/translator/ConstantUnion.h',
             'compiler/translator/Diagnostics.cpp',
             'compiler/translator/Diagnostics.h',
             'compiler/translator/DirectiveHandler.cpp',
             'compiler/translator/DirectiveHandler.h',
             'compiler/translator/EmulatePrecision.cpp',
             'compiler/translator/EmulatePrecision.h',
             'compiler/translator/ExtensionBehavior.h',
-            'compiler/translator/ExtensionGLSL.cpp',
-            'compiler/translator/ExtensionGLSL.h',
             'compiler/translator/FlagStd140Structs.cpp',
             'compiler/translator/FlagStd140Structs.h',
             'compiler/translator/ForLoopUnroll.cpp',
             'compiler/translator/ForLoopUnroll.h',
             'compiler/translator/HashNames.h',
             'compiler/translator/InfoSink.cpp',
             'compiler/translator/InfoSink.h',
             'compiler/translator/Initialize.cpp',
@@ -67,22 +63,16 @@
             'compiler/translator/Intermediate.h',
             'compiler/translator/Intermediate.cpp',
             'compiler/translator/LoopInfo.cpp',
             'compiler/translator/LoopInfo.h',
             'compiler/translator/MMap.h',
             'compiler/translator/NodeSearch.h',
             'compiler/translator/Operator.cpp',
             'compiler/translator/Operator.h',
-            'compiler/translator/OutputESSL.cpp',
-            'compiler/translator/OutputESSL.h',
-            'compiler/translator/OutputGLSL.cpp',
-            'compiler/translator/OutputGLSL.h',
-            'compiler/translator/OutputGLSLBase.cpp',
-            'compiler/translator/OutputGLSLBase.h',
             'compiler/translator/ParseContext.cpp',
             'compiler/translator/ParseContext.h',
             'compiler/translator/PoolAlloc.cpp',
             'compiler/translator/PoolAlloc.h',
             'compiler/translator/Pragma.h',
             'compiler/translator/PruneEmptyDeclarations.cpp',
             'compiler/translator/PruneEmptyDeclarations.h',
             'compiler/translator/RecordConstantPrecision.cpp',
@@ -95,38 +85,32 @@
             'compiler/translator/RewriteDoWhile.h',
             'compiler/translator/RenameFunction.h',
             'compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp',
             'compiler/translator/ScalarizeVecAndMatConstructorArgs.h',
             'compiler/translator/SearchSymbol.cpp',
             'compiler/translator/SearchSymbol.h',
             'compiler/translator/SymbolTable.cpp',
             'compiler/translator/SymbolTable.h',
-            'compiler/translator/TranslatorESSL.cpp',
-            'compiler/translator/TranslatorESSL.h',
-            'compiler/translator/TranslatorGLSL.cpp',
-            'compiler/translator/TranslatorGLSL.h',
             'compiler/translator/Types.cpp',
             'compiler/translator/Types.h',
             'compiler/translator/UnfoldShortCircuitAST.cpp',
             'compiler/translator/UnfoldShortCircuitAST.h',
             'compiler/translator/ValidateGlobalInitializer.cpp',
             'compiler/translator/ValidateGlobalInitializer.h',
             'compiler/translator/ValidateLimitations.cpp',
             'compiler/translator/ValidateLimitations.h',
             'compiler/translator/ValidateOutputs.cpp',
             'compiler/translator/ValidateOutputs.h',
             'compiler/translator/ValidateSwitch.cpp',
             'compiler/translator/ValidateSwitch.h',
             'compiler/translator/VariableInfo.cpp',
             'compiler/translator/VariableInfo.h',
             'compiler/translator/VariablePacker.cpp',
             'compiler/translator/VariablePacker.h',
-            'compiler/translator/VersionGLSL.cpp',
-            'compiler/translator/VersionGLSL.h',
             'compiler/translator/blocklayout.cpp',
             'compiler/translator/blocklayout.h',
             'compiler/translator/depgraph/DependencyGraph.cpp',
             'compiler/translator/depgraph/DependencyGraph.h',
             'compiler/translator/depgraph/DependencyGraphBuilder.cpp',
             'compiler/translator/depgraph/DependencyGraphBuilder.h',
             'compiler/translator/depgraph/DependencyGraphOutput.cpp',
             'compiler/translator/depgraph/DependencyGraphOutput.h',
@@ -143,16 +127,38 @@
             'compiler/translator/timing/RestrictFragmentShaderTiming.h',
             'compiler/translator/timing/RestrictVertexShaderTiming.cpp',
             'compiler/translator/timing/RestrictVertexShaderTiming.h',
             'compiler/translator/util.cpp',
             'compiler/translator/util.h',
             'third_party/compiler/ArrayBoundsClamper.cpp',
             'third_party/compiler/ArrayBoundsClamper.h',
         ],
+        'angle_translator_lib_essl_sources':
+        [
+            'compiler/translator/OutputESSL.cpp',
+            'compiler/translator/OutputESSL.h',
+            'compiler/translator/TranslatorESSL.cpp',
+            'compiler/translator/TranslatorESSL.h',
+        ],
+        'angle_translator_lib_glsl_sources':
+        [
+            'compiler/translator/BuiltInFunctionEmulatorGLSL.cpp',
+            'compiler/translator/BuiltInFunctionEmulatorGLSL.h',
+            'compiler/translator/ExtensionGLSL.cpp',
+            'compiler/translator/ExtensionGLSL.h',
+            'compiler/translator/OutputGLSL.cpp',
+            'compiler/translator/OutputGLSL.h',
+            'compiler/translator/OutputGLSLBase.cpp',
+            'compiler/translator/OutputGLSLBase.h',
+            'compiler/translator/TranslatorGLSL.cpp',
+            'compiler/translator/TranslatorGLSL.h',
+            'compiler/translator/VersionGLSL.cpp',
+            'compiler/translator/VersionGLSL.h',
+        ],
         'angle_translator_lib_hlsl_sources':
         [
             'compiler/translator/ArrayReturnValueToOutParameter.cpp',
             'compiler/translator/ArrayReturnValueToOutParameter.h',
             'compiler/translator/ASTMetadataHLSL.cpp',
             'compiler/translator/ASTMetadataHLSL.h',
             'compiler/translator/blocklayoutHLSL.cpp',
             'compiler/translator/blocklayoutHLSL.h',
@@ -248,16 +254,52 @@
             {
               'VCLibrarianTool':
               {
                 'AdditionalOptions': ['/ignore:4221']
               },
             },
             'conditions':
             [
+                ['angle_enable_essl==1',
+                {
+                    'defines':
+                    [
+                        'ANGLE_ENABLE_ESSL',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_ESSL',
+                        ],
+                    },
+                    'sources':
+                    [
+                        '<@(angle_translator_lib_essl_sources)',
+                    ],
+                }],
+                ['angle_enable_glsl==1',
+                {
+                    'defines':
+                    [
+                        'ANGLE_ENABLE_GLSL',
+                    ],
+                    'direct_dependent_settings':
+                    {
+                        'defines':
+                        [
+                            'ANGLE_ENABLE_GLSL',
+                        ],
+                    },
+                    'sources':
+                    [
+                        '<@(angle_translator_lib_glsl_sources)',
+                    ],
+                }],
                 ['angle_enable_hlsl==1',
                 {
                     'defines':
                     [
                         'ANGLE_ENABLE_HLSL',
                     ],
                     'direct_dependent_settings':
                     {
--- a/gfx/angle/src/compiler/translator/CallDAG.cpp
+++ b/gfx/angle/src/compiler/translator/CallDAG.cpp
@@ -30,16 +30,17 @@ class CallDAG::CallDAGCreator : public T
         for (auto &it : mFunctions)
         {
             // Skip unimplemented functions
             if (it.second.node)
             {
                 InitResult result = assignIndicesInternal(&it.second);
                 if (result != INITDAG_SUCCESS)
                 {
+                    *mCreationInfo << "\n";
                     return result;
                 }
             }
             else
             {
                 skipped++;
             }
         }
@@ -102,17 +103,18 @@ class CallDAG::CallDAGCreator : public T
     bool visitAggregate(Visit visit, TIntermAggregate *node) override
     {
         switch (node->getOp())
         {
           case EOpPrototype:
             if (visit == PreVisit)
             {
                 // Function declaration, create an empty record.
-                mFunctions[node->getName()];
+                auto& record = mFunctions[node->getName()];
+                record.name = node->getName();
             }
             break;
           case EOpFunction:
             {
                 // Function definition, create the record if need be and remember the node.
                 if (visit == PreVisit)
                 {
                     auto it = mFunctions.find(node->getName());
@@ -164,51 +166,48 @@ class CallDAG::CallDAGCreator : public T
 
     // Recursively assigns indices to a sub DAG
     InitResult assignIndicesInternal(CreatorFunctionData *function)
     {
         ASSERT(function);
 
         if (!function->node)
         {
-            *mCreationInfo << "Undefined function: " << function->name;
+            *mCreationInfo << "Undefined function '" << function->name
+                           << ")' used in the following call chain:";
             return INITDAG_UNDEFINED;
         }
 
         if (function->indexAssigned)
         {
             return INITDAG_SUCCESS;
         }
 
         if (function->visiting)
         {
             if (mCreationInfo)
             {
-                *mCreationInfo << "Recursive function call in the following call chain: " << function->name;
+                *mCreationInfo << "Recursive function call in the following call chain:" << function->name;
             }
             return INITDAG_RECURSION;
         }
         function->visiting = true;
 
         for (auto &callee : function->callees)
         {
             InitResult result = assignIndicesInternal(callee);
-            if (result == INITDAG_RECURSION)
+            if (result != INITDAG_SUCCESS)
             {
-                // We know that there is a recursive function call chain in the AST,
+                // We know that there is an issue with the call chain in the AST,
                 // print the link of the chain we were processing.
                 if (mCreationInfo)
                 {
-                    *mCreationInfo << " <- " << function->name;
+                    *mCreationInfo << " <- " << function->name << ")";
                 }
-                return INITDAG_RECURSION;
-            }
-            else if (result == INITDAG_UNDEFINED)
-            {
-                return INITDAG_UNDEFINED;
+                return result;
             }
         }
 
         function->index = mCurrentIndex++;
         function->indexAssigned = true;
 
         function->visiting = false;
         return INITDAG_SUCCESS;
--- a/gfx/angle/src/compiler/translator/CodeGen.cpp
+++ b/gfx/angle/src/compiler/translator/CodeGen.cpp
@@ -1,55 +1,74 @@
 //
 // Copyright (c) 2013 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.
 //
 
+#ifdef ANGLE_ENABLE_ESSL
 #include "compiler/translator/TranslatorESSL.h"
+#endif
+
+#ifdef ANGLE_ENABLE_GLSL
 #include "compiler/translator/TranslatorGLSL.h"
+#endif
+
 #ifdef ANGLE_ENABLE_HLSL
 #include "compiler/translator/TranslatorHLSL.h"
 #endif // ANGLE_ENABLE_HLSL
 
 //
 // This function must be provided to create the actual
 // compile object used by higher level code.  It returns
 // a subclass of TCompiler.
 //
 TCompiler* ConstructCompiler(
     sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
 {
     switch (output) {
       case SH_ESSL_OUTPUT:
+#ifdef ANGLE_ENABLE_ESSL
         return new TranslatorESSL(type, spec);
+#else
+        // This compiler is not supported in this
+        // configuration. Return NULL per the ShConstructCompiler API.
+        return nullptr;
+#endif // ANGLE_ENABLE_ESSL
       case SH_GLSL_130_OUTPUT:
       case SH_GLSL_140_OUTPUT:
       case SH_GLSL_150_CORE_OUTPUT:
       case SH_GLSL_330_CORE_OUTPUT:
       case SH_GLSL_400_CORE_OUTPUT:
       case SH_GLSL_410_CORE_OUTPUT:
       case SH_GLSL_420_CORE_OUTPUT:
       case SH_GLSL_430_CORE_OUTPUT:
       case SH_GLSL_440_CORE_OUTPUT:
       case SH_GLSL_450_CORE_OUTPUT:
       case SH_GLSL_COMPATIBILITY_OUTPUT:
+#ifdef ANGLE_ENABLE_GLSL
         return new TranslatorGLSL(type, spec, output);
-      case SH_HLSL9_OUTPUT:
-      case SH_HLSL11_OUTPUT:
+#else
+        // This compiler is not supported in this
+        // configuration. Return NULL per the ShConstructCompiler API.
+        return nullptr;
+#endif // ANGLE_ENABLE_GLSL
+      case SH_HLSL_3_0_OUTPUT:
+      case SH_HLSL_4_1_OUTPUT:
+      case SH_HLSL_4_0_FL9_3_OUTPUT:
 #ifdef ANGLE_ENABLE_HLSL
         return new TranslatorHLSL(type, spec, output);
 #else
         // This compiler is not supported in this
         // configuration. Return NULL per the ShConstructCompiler API.
-        return NULL;
+        return nullptr;
 #endif // ANGLE_ENABLE_HLSL
       default:
         // Unknown format. Return NULL per the ShConstructCompiler API.
-        return NULL;
+        return nullptr;
     }
 }
 
 //
 // Delete the compiler made by ConstructCompiler
 //
 void DeleteCompiler(TCompiler* compiler)
 {
--- a/gfx/angle/src/compiler/translator/Common.h
+++ b/gfx/angle/src/compiler/translator/Common.h
@@ -55,28 +55,31 @@ inline TString* NewPoolTString(const cha
 // across compiles.
 //
 #define TPersistString std::string
 #define TPersistStringStream std::ostringstream
 
 //
 // Pool allocator versions of vectors, lists, and maps
 //
-template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
-public:
-    typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
-    TVector() : std::vector<T, pool_allocator<T> >() {}
-    TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
-    TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {}
+template <class T>
+class TVector : public std::vector<T, pool_allocator<T>>
+{
+  public:
+    typedef typename std::vector<T, pool_allocator<T>>::size_type size_type;
+    TVector() : std::vector<T, pool_allocator<T>>() {}
+    TVector(const pool_allocator<T> &a) : std::vector<T, pool_allocator<T>>(a) {}
+    TVector(size_type i) : std::vector<T, pool_allocator<T>>(i) {}
 };
 
-template <class K, class D, class CMP = std::less<K> > 
-class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D> > > {
-public:
-    typedef pool_allocator<std::pair<const K, D> > tAllocator;
+template <class K, class D, class CMP = std::less<K>>
+class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D>>>
+{
+  public:
+    typedef pool_allocator<std::pair<const K, D>> tAllocator;
 
     TMap() : std::map<K, D, CMP, tAllocator>() {}
     // use correct two-stage name lookup supported in gcc 3.4 and above
     TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {}
 };
 
 // Integer to TString conversion
 template <typename T>
--- a/gfx/angle/src/compiler/translator/Compiler.cpp
+++ b/gfx/angle/src/compiler/translator/Compiler.cpp
@@ -317,17 +317,20 @@ TIntermNode *TCompiler::compileTreeImpl(
             initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
             builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
         }
 
         // Clamping uniform array bounds needs to happen after validateLimitations pass.
         if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
             arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
 
-        if (success && shaderType == GL_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION))
+        // gl_Position is always written in compatibility output mode
+        if (success && shaderType == GL_VERTEX_SHADER &&
+            ((compileOptions & SH_INIT_GL_POSITION) ||
+             (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
             initializeGLPosition(root);
 
         // This pass might emit short circuits so keep it before the short circuit unfolding
         if (success && (compileOptions & SH_REWRITE_DO_WHILE_LOOPS))
             RewriteDoWhile(root, getTemporaryIndex());
 
         if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
         {
@@ -602,17 +605,17 @@ bool TCompiler::tagUsedFunctions()
         if (mCallDag.getRecordFromIndex(i).name == "main(")
         {
             internalTagUsedFunction(i);
             return true;
         }
     }
 
     infoSink.info.prefix(EPrefixError);
-    infoSink.info << "Missing main()";
+    infoSink.info << "Missing main()\n";
     return false;
 }
 
 void TCompiler::internalTagUsedFunction(size_t index)
 {
     if (functionMetadata[index].used)
     {
         return;
@@ -739,27 +742,16 @@ bool TCompiler::limitExpressionComplexit
     root->traverse(&traverser);
 
     if (traverser.getMaxDepth() > maxExpressionComplexity)
     {
         infoSink.info << "Expression too complex.";
         return false;
     }
 
-    TDependencyGraph graph(root);
-
-    for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
-         iter != graph.endUserDefinedFunctionCalls();
-         ++iter)
-    {
-        TGraphFunctionCall* samplerSymbol = *iter;
-        TDependencyGraphTraverser graphTraverser;
-        samplerSymbol->traverse(&graphTraverser);
-    }
-
     return true;
 }
 
 bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
 {
     RestrictFragmentShaderTiming restrictor(infoSink.info);
     restrictor.enforceRestrictions(graph);
     return restrictor.numErrors() == 0;
--- a/gfx/angle/src/compiler/translator/DirectiveHandler.cpp
+++ b/gfx/angle/src/compiler/translator/DirectiveHandler.cpp
@@ -3,16 +3,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #include "compiler/translator/DirectiveHandler.h"
 
 #include <sstream>
 
+#include "angle_gl.h"
 #include "common/debug.h"
 #include "compiler/translator/Diagnostics.h"
 
 static TBehavior getBehavior(const std::string& str)
 {
     const char kRequire[] = "require";
     const char kEnable[] = "enable";
     const char kDisable[] = "disable";
@@ -20,23 +21,25 @@ static TBehavior getBehavior(const std::
 
     if (str == kRequire) return EBhRequire;
     else if (str == kEnable) return EBhEnable;
     else if (str == kDisable) return EBhDisable;
     else if (str == kWarn) return EBhWarn;
     return EBhUndefined;
 }
 
-TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior,
-                                     TDiagnostics& diagnostics,
-                                     int& shaderVersion,
+TDirectiveHandler::TDirectiveHandler(TExtensionBehavior &extBehavior,
+                                     TDiagnostics &diagnostics,
+                                     int &shaderVersion,
+                                     sh::GLenum shaderType,
                                      bool debugShaderPrecisionSupported)
     : mExtensionBehavior(extBehavior),
       mDiagnostics(diagnostics),
       mShaderVersion(shaderVersion),
+      mShaderType(shaderType),
       mDebugShaderPrecisionSupported(debugShaderPrecisionSupported)
 {
 }
 
 TDirectiveHandler::~TDirectiveHandler()
 {
 }
 
@@ -52,17 +55,26 @@ void TDirectiveHandler::handlePragma(con
                                      bool stdgl)
 {
     if (stdgl)
     {
         const char kInvariant[] = "invariant";
         const char kAll[] = "all";
 
         if (name == kInvariant && value == kAll)
+        {
+            if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER)
+            {
+                // ESSL 3.00.4 section 4.6.1
+                mDiagnostics.writeInfo(
+                    pp::Diagnostics::PP_ERROR, loc,
+                    "#pragma STDGL invariant(all) can not be used in fragment shader", name, value);
+            }
             mPragma.stdgl.invariantAll = true;
+        }
         // The STDGL pragma is used to reserve pragmas for use by future
         // revisions of GLSL.  Do not generate an error on unexpected
         // name and value.
         return;
     }
     else
     {
         const char kOptimize[] = "optimize";
--- a/gfx/angle/src/compiler/translator/DirectiveHandler.h
+++ b/gfx/angle/src/compiler/translator/DirectiveHandler.h
@@ -6,25 +6,27 @@
 
 #ifndef COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
 #define COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
 
 #include "common/angleutils.h"
 #include "compiler/translator/ExtensionBehavior.h"
 #include "compiler/translator/Pragma.h"
 #include "compiler/preprocessor/DirectiveHandlerBase.h"
+#include "GLSLANG/ShaderLang.h"
 
 class TDiagnostics;
 
 class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
 {
   public:
-    TDirectiveHandler(TExtensionBehavior& extBehavior,
-                      TDiagnostics& diagnostics,
-                      int& shaderVersion,
+    TDirectiveHandler(TExtensionBehavior &extBehavior,
+                      TDiagnostics &diagnostics,
+                      int &shaderVersion,
+                      sh::GLenum shaderType,
                       bool debugShaderPrecisionSupported);
     ~TDirectiveHandler() override;
 
     const TPragma& pragma() const { return mPragma; }
     const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; }
 
     void handleError(const pp::SourceLocation &loc, const std::string &msg) override;
 
@@ -39,12 +41,13 @@ class TDirectiveHandler : public pp::Dir
 
     void handleVersion(const pp::SourceLocation &loc, int version) override;
 
   private:
     TPragma mPragma;
     TExtensionBehavior& mExtensionBehavior;
     TDiagnostics& mDiagnostics;
     int& mShaderVersion;
+    sh::GLenum mShaderType;
     bool mDebugShaderPrecisionSupported;
 };
 
 #endif  // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
--- a/gfx/angle/src/compiler/translator/OutputHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/OutputHLSL.cpp
@@ -78,29 +78,19 @@ const TConstantUnion *WriteConstantUnion
 
 namespace sh
 {
 
 TString OutputHLSL::TextureFunction::name() const
 {
     TString name = "gl_texture";
 
-    if (IsSampler2D(sampler))
-    {
-        name += "2D";
-    }
-    else if (IsSampler3D(sampler))
-    {
-        name += "3D";
-    }
-    else if (IsSamplerCube(sampler))
-    {
-        name += "Cube";
-    }
-    else UNREACHABLE();
+    // We need to include full the sampler type in the function name to make the signature unique
+    // on D3D11, where samplers are passed to texture functions as indices.
+    name += TextureTypeSuffix(this->sampler);
 
     if (proj)
     {
         name += "Proj";
     }
 
     if (offset)
     {
@@ -180,17 +170,17 @@ OutputHLSL::OutputHLSL(sh::GLenum shader
     mInsideDiscontinuousLoop = false;
     mNestedLoopDepth = 0;
 
     mExcessiveLoopIndex = NULL;
 
     mStructureHLSL = new StructureHLSL;
     mUniformHLSL = new UniformHLSL(mStructureHLSL, outputType, uniforms);
 
-    if (mOutputType == SH_HLSL9_OUTPUT)
+    if (mOutputType == SH_HLSL_3_0_OUTPUT)
     {
         // Fragment shaders need dx_DepthRange, dx_ViewCoords and dx_DepthFront.
         // Vertex shaders need a slightly different set: dx_DepthRange, dx_ViewCoords and dx_ViewAdjust.
         // In both cases total 3 uniform registers need to be reserved.
         mUniformHLSL->reserveUniformRegisters(3);
     }
 
     // Reserve registers for the default uniform block and driver constants
@@ -367,17 +357,17 @@ void OutputHLSL::header(TInfoSinkBase &o
         const TType &type = attribute->second->getType();
         const TString &name = attribute->second->getSymbol();
 
         attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n";
     }
 
     out << mStructureHLSL->structsHeader();
 
-    out << mUniformHLSL->uniformsHeader(mOutputType, mReferencedUniforms);
+    mUniformHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms);
     out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks);
 
     if (!mEqualityFunctions.empty())
     {
         out << "\n// Equality functions\n\n";
         for (const auto &eqFunction : mEqualityFunctions)
         {
             out << eqFunction->functionDefinition << "\n";
@@ -490,17 +480,17 @@ void OutputHLSL::header(TInfoSinkBase &o
                    "{\n"
                    "    float near;\n"
                    "    float far;\n"
                    "    float diff;\n"
                    "};\n"
                    "\n";
         }
 
-        if (mOutputType == SH_HLSL11_OUTPUT)
+        if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
         {
             out << "cbuffer DriverConstants : register(b1)\n"
                    "{\n";
 
             if (mUsesDepthRange)
             {
                 out << "    float3 dx_DepthRange : packoffset(c0);\n";
             }
@@ -510,16 +500,23 @@ void OutputHLSL::header(TInfoSinkBase &o
                 out << "    float4 dx_ViewCoords : packoffset(c1);\n";
             }
 
             if (mUsesFragCoord || mUsesFrontFacing)
             {
                 out << "    float3 dx_DepthFront : packoffset(c2);\n";
             }
 
+            if (mUsesFragCoord)
+            {
+                // dx_ViewScale is only used in the fragment shader to correct
+                // the value for glFragCoord if necessary
+                out << "    float2 dx_ViewScale : packoffset(c3);\n";
+            }
+
             out << "};\n";
         }
         else
         {
             if (mUsesDepthRange)
             {
                 out << "uniform float3 dx_DepthRange : register(c0);";
             }
@@ -594,31 +591,33 @@ void OutputHLSL::header(TInfoSinkBase &o
                    "{\n"
                    "    float near;\n"
                    "    float far;\n"
                    "    float diff;\n"
                    "};\n"
                    "\n";
         }
 
-        if (mOutputType == SH_HLSL11_OUTPUT)
+        if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
         {
             out << "cbuffer DriverConstants : register(b1)\n"
                     "{\n";
 
             if (mUsesDepthRange)
             {
                 out << "    float3 dx_DepthRange : packoffset(c0);\n";
             }
 
-            // dx_ViewAdjust and dx_ViewCoords will only be used in Feature Level 9 shaders.
-            // However, we declare it for all shaders (including Feature Level 10+).
-            // The bytecode is the same whether we declare it or not, since D3DCompiler removes it if it's unused.
+            // dx_ViewAdjust and dx_ViewCoords will only be used in Feature Level 9
+            // shaders. However, we declare it for all shaders (including Feature Level 10+).
+            // The bytecode is the same whether we declare it or not, since D3DCompiler removes it
+            // if it's unused.
             out << "    float4 dx_ViewAdjust : packoffset(c1);\n";
             out << "    float2 dx_ViewCoords : packoffset(c2);\n";
+            out << "    float2 dx_ViewScale  : packoffset(c3);\n";
 
             out << "};\n"
                    "\n";
         }
         else
         {
             if (mUsesDepthRange)
             {
@@ -694,17 +693,17 @@ void OutputHLSL::header(TInfoSinkBase &o
         }
 
         // Function name
         out << textureFunction->name();
 
         // Argument list
         int hlslCoords = 4;
 
-        if (mOutputType == SH_HLSL9_OUTPUT)
+        if (mOutputType == SH_HLSL_3_0_OUTPUT)
         {
             switch(textureFunction->sampler)
             {
               case EbtSampler2D:   out << "sampler2D s";   hlslCoords = 2; break;
               case EbtSamplerCube: out << "samplerCUBE s"; hlslCoords = 3; break;
               default: UNREACHABLE();
             }
 
@@ -713,39 +712,30 @@ void OutputHLSL::header(TInfoSinkBase &o
               case TextureFunction::IMPLICIT:                 break;
               case TextureFunction::BIAS:     hlslCoords = 4; break;
               case TextureFunction::LOD:      hlslCoords = 4; break;
               case TextureFunction::LOD0:     hlslCoords = 4; break;
               case TextureFunction::LOD0BIAS: hlslCoords = 4; break;
               default: UNREACHABLE();
             }
         }
-        else if (mOutputType == SH_HLSL11_OUTPUT)
+        else
         {
-            switch(textureFunction->sampler)
+            hlslCoords = HLSLTextureCoordsCount(textureFunction->sampler);
+            if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
             {
-              case EbtSampler2D:            out << "Texture2D x, SamplerState s";                hlslCoords = 2; break;
-              case EbtSampler3D:            out << "Texture3D x, SamplerState s";                hlslCoords = 3; break;
-              case EbtSamplerCube:          out << "TextureCube x, SamplerState s";              hlslCoords = 3; break;
-              case EbtSampler2DArray:       out << "Texture2DArray x, SamplerState s";           hlslCoords = 3; break;
-              case EbtISampler2D:           out << "Texture2D<int4> x, SamplerState s";          hlslCoords = 2; break;
-              case EbtISampler3D:           out << "Texture3D<int4> x, SamplerState s";          hlslCoords = 3; break;
-              case EbtISamplerCube:         out << "Texture2DArray<int4> x, SamplerState s";     hlslCoords = 3; break;
-              case EbtISampler2DArray:      out << "Texture2DArray<int4> x, SamplerState s";     hlslCoords = 3; break;
-              case EbtUSampler2D:           out << "Texture2D<uint4> x, SamplerState s";         hlslCoords = 2; break;
-              case EbtUSampler3D:           out << "Texture3D<uint4> x, SamplerState s";         hlslCoords = 3; break;
-              case EbtUSamplerCube:         out << "Texture2DArray<uint4> x, SamplerState s";    hlslCoords = 3; break;
-              case EbtUSampler2DArray:      out << "Texture2DArray<uint4> x, SamplerState s";    hlslCoords = 3; break;
-              case EbtSampler2DShadow:      out << "Texture2D x, SamplerComparisonState s";      hlslCoords = 2; break;
-              case EbtSamplerCubeShadow:    out << "TextureCube x, SamplerComparisonState s";    hlslCoords = 3; break;
-              case EbtSampler2DArrayShadow: out << "Texture2DArray x, SamplerComparisonState s"; hlslCoords = 3; break;
-              default: UNREACHABLE();
+                out << TextureString(textureFunction->sampler) << " x, "
+                    << SamplerString(textureFunction->sampler) << " s";
+            }
+            else
+            {
+                ASSERT(mOutputType == SH_HLSL_4_1_OUTPUT);
+                out << "const uint samplerIndex";
             }
         }
-        else UNREACHABLE();
 
         if (textureFunction->method == TextureFunction::FETCH)   // Integer coordinates
         {
             switch(textureFunction->coords)
             {
               case 2: out << ", int2 t"; break;
               case 3: out << ", int3 t"; break;
               default: UNREACHABLE();
@@ -826,35 +816,63 @@ void OutputHLSL::header(TInfoSinkBase &o
             textureFunction->method == TextureFunction::LOD0BIAS)
         {
             out << ", float bias";
         }
 
         out << ")\n"
                "{\n";
 
+        // In some cases we use a variable to store the texture/sampler objects, but to work around
+        // a D3D11 compiler bug related to discard inside a loop that is conditional on texture
+        // sampling we need to call the function directly on a reference to the array. The bug was
+        // found using dEQP-GLES3.functional.shaders.discard*loop_texture* tests.
+        TString textureReference("x");
+        TString samplerReference("s");
+        if (mOutputType == SH_HLSL_4_1_OUTPUT)
+        {
+            TString suffix = TextureGroupSuffix(textureFunction->sampler);
+            if (TextureGroup(textureFunction->sampler) == HLSL_TEXTURE_2D)
+            {
+                textureReference = TString("textures") + suffix + "[samplerIndex]";
+                samplerReference = TString("samplers") + suffix + "[samplerIndex]";
+            }
+            else
+            {
+                out << "    const uint textureIndex = samplerIndex - textureIndexOffset" << suffix
+                    << ";\n";
+                textureReference = TString("textures") + suffix + "[textureIndex]";
+                out << "    const uint samplerArrayIndex = samplerIndex - samplerIndexOffset"
+                    << suffix << ";\n";
+                samplerReference = TString("samplers") + suffix + "[samplerArrayIndex]";
+            }
+        }
+
         if (textureFunction->method == TextureFunction::SIZE)
         {
             if (IsSampler2D(textureFunction->sampler) || IsSamplerCube(textureFunction->sampler))
             {
                 if (IsSamplerArray(textureFunction->sampler))
                 {
                     out << "    uint width; uint height; uint layers; uint numberOfLevels;\n"
-                           "    x.GetDimensions(lod, width, height, layers, numberOfLevels);\n";
+                        << "    " << textureReference
+                        << ".GetDimensions(lod, width, height, layers, numberOfLevels);\n";
                 }
                 else
                 {
                     out << "    uint width; uint height; uint numberOfLevels;\n"
-                           "    x.GetDimensions(lod, width, height, numberOfLevels);\n";
+                        << "    " << textureReference
+                        << ".GetDimensions(lod, width, height, numberOfLevels);\n";
                 }
             }
             else if (IsSampler3D(textureFunction->sampler))
             {
                 out << "    uint width; uint height; uint depth; uint numberOfLevels;\n"
-                       "    x.GetDimensions(lod, width, height, depth, numberOfLevels);\n";
+                    << "    " << textureReference
+                    << ".GetDimensions(lod, width, height, depth, numberOfLevels);\n";
             }
             else UNREACHABLE();
 
             switch(textureFunction->sampler)
             {
               case EbtSampler2D:            out << "    return int2(width, height);";         break;
               case EbtSampler3D:            out << "    return int3(width, height, depth);";  break;
               case EbtSamplerCube:          out << "    return int2(width, height);";         break;
@@ -876,17 +894,18 @@ void OutputHLSL::header(TInfoSinkBase &o
         else
         {
             if (IsIntegerSampler(textureFunction->sampler) && IsSamplerCube(textureFunction->sampler))
             {
                 out << "    float width; float height; float layers; float levels;\n";
 
                 out << "    uint mip = 0;\n";
 
-                out << "    x.GetDimensions(mip, width, height, layers, levels);\n";
+                out << "    " << textureReference
+                    << ".GetDimensions(mip, width, height, layers, levels);\n";
 
                 out << "    bool xMajor = abs(t.x) > abs(t.y) && abs(t.x) > abs(t.z);\n";
                 out << "    bool yMajor = abs(t.y) > abs(t.z) && abs(t.y) > abs(t.x);\n";
                 out << "    bool zMajor = abs(t.z) > abs(t.x) && abs(t.z) > abs(t.y);\n";
                 out << "    bool negative = (xMajor && t.x < 0.0f) || (yMajor && t.y < 0.0f) || (zMajor && t.z < 0.0f);\n";
 
                 // FACE_POSITIVE_X = 000b
                 // FACE_NEGATIVE_X = 001b
@@ -906,17 +925,18 @@ void OutputHLSL::header(TInfoSinkBase &o
                 // Mip level computation.
                 if (textureFunction->method == TextureFunction::IMPLICIT)
                 {
                     out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
                            "    float2 dx = ddx(tSized);\n"
                            "    float2 dy = ddy(tSized);\n"
                            "    float lod = 0.5f * log2(max(dot(dx, dx), dot(dy, dy)));\n"
                            "    mip = uint(min(max(round(lod), 0), levels - 1));\n"
-                           "    x.GetDimensions(mip, width, height, layers, levels);\n";
+                        << "    " << textureReference
+                        << ".GetDimensions(mip, width, height, layers, levels);\n";
                 }
             }
             else if (IsIntegerSampler(textureFunction->sampler) &&
                      textureFunction->method != TextureFunction::FETCH)
             {
                 if (IsSampler2D(textureFunction->sampler))
                 {
                     if (IsSamplerArray(textureFunction->sampler))
@@ -929,17 +949,18 @@ void OutputHLSL::header(TInfoSinkBase &o
                         }
                         else if (textureFunction->method == TextureFunction::LOD0BIAS)
                         {
                             out << "    uint mip = bias;\n";
                         }
                         else
                         {
 
-                            out << "    x.GetDimensions(0, width, height, layers, levels);\n";
+                            out << "    " << textureReference
+                                << ".GetDimensions(0, width, height, layers, levels);\n";
                             if (textureFunction->method == TextureFunction::IMPLICIT ||
                                 textureFunction->method == TextureFunction::BIAS)
                             {
                                 out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
                                        "    float dx = length(ddx(tSized));\n"
                                        "    float dy = length(ddy(tSized));\n"
                                        "    float lod = log2(max(dx, dy));\n";
 
@@ -951,33 +972,35 @@ void OutputHLSL::header(TInfoSinkBase &o
                             else if (textureFunction->method == TextureFunction::GRAD)
                             {
                                 out << "    float lod = log2(max(length(ddx), length(ddy)));\n";
                             }
 
                             out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
                         }
 
-                        out << "    x.GetDimensions(mip, width, height, layers, levels);\n";
+                        out << "    " << textureReference
+                            << ".GetDimensions(mip, width, height, layers, levels);\n";
                     }
                     else
                     {
                         out << "    float width; float height; float levels;\n";
 
                         if (textureFunction->method == TextureFunction::LOD0)
                         {
                             out << "    uint mip = 0;\n";
                         }
                         else if (textureFunction->method == TextureFunction::LOD0BIAS)
                         {
                             out << "    uint mip = bias;\n";
                         }
                         else
                         {
-                            out << "    x.GetDimensions(0, width, height, levels);\n";
+                            out << "    " << textureReference
+                                << ".GetDimensions(0, width, height, levels);\n";
 
                             if (textureFunction->method == TextureFunction::IMPLICIT ||
                                 textureFunction->method == TextureFunction::BIAS)
                             {
                                 out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
                                        "    float dx = length(ddx(tSized));\n"
                                        "    float dy = length(ddy(tSized));\n"
                                        "    float lod = log2(max(dx, dy));\n";
@@ -990,34 +1013,36 @@ void OutputHLSL::header(TInfoSinkBase &o
                             else if (textureFunction->method == TextureFunction::GRAD)
                             {
                                 out << "    float lod = log2(max(length(ddx), length(ddy)));\n";
                             }
 
                             out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
                         }
 
-                        out << "    x.GetDimensions(mip, width, height, levels);\n";
+                        out << "    " << textureReference
+                            << ".GetDimensions(mip, width, height, levels);\n";
                     }
                 }
                 else if (IsSampler3D(textureFunction->sampler))
                 {
                     out << "    float width; float height; float depth; float levels;\n";
 
                     if (textureFunction->method == TextureFunction::LOD0)
                     {
                         out << "    uint mip = 0;\n";
                     }
                     else if (textureFunction->method == TextureFunction::LOD0BIAS)
                     {
                         out << "    uint mip = bias;\n";
                     }
                     else
                     {
-                        out << "    x.GetDimensions(0, width, height, depth, levels);\n";
+                        out << "    " << textureReference
+                            << ".GetDimensions(0, width, height, depth, levels);\n";
 
                         if (textureFunction->method == TextureFunction::IMPLICIT ||
                             textureFunction->method == TextureFunction::BIAS)
                         {
                             out << "    float3 tSized = float3(t.x * width, t.y * height, t.z * "
                                    "depth);\n"
                                    "    float dx = length(ddx(tSized));\n"
                                    "    float dy = length(ddy(tSized));\n"
@@ -1031,86 +1056,127 @@ void OutputHLSL::header(TInfoSinkBase &o
                         else if (textureFunction->method == TextureFunction::GRAD)
                         {
                             out << "    float lod = log2(max(length(ddx), length(ddy)));\n";
                         }
 
                         out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
                     }
 
-                    out << "    x.GetDimensions(mip, width, height, depth, levels);\n";
+                    out << "    " << textureReference
+                        << ".GetDimensions(mip, width, height, depth, levels);\n";
                 }
                 else UNREACHABLE();
             }
 
             out << "    return ";
 
             // HLSL intrinsic
-            if (mOutputType == SH_HLSL9_OUTPUT)
+            if (mOutputType == SH_HLSL_3_0_OUTPUT)
             {
                 switch(textureFunction->sampler)
                 {
                   case EbtSampler2D:   out << "tex2D";   break;
                   case EbtSamplerCube: out << "texCUBE"; break;
                   default: UNREACHABLE();
                 }
 
                 switch(textureFunction->method)
                 {
-                  case TextureFunction::IMPLICIT: out << "(s, ";     break;
-                  case TextureFunction::BIAS:     out << "bias(s, "; break;
-                  case TextureFunction::LOD:      out << "lod(s, ";  break;
-                  case TextureFunction::LOD0:     out << "lod(s, ";  break;
-                  case TextureFunction::LOD0BIAS: out << "lod(s, ";  break;
+                    case TextureFunction::IMPLICIT:
+                        out << "(" << samplerReference << ", ";
+                        break;
+                    case TextureFunction::BIAS:
+                        out << "bias(" << samplerReference << ", ";
+                        break;
+                    case TextureFunction::LOD:
+                        out << "lod(" << samplerReference << ", ";
+                        break;
+                    case TextureFunction::LOD0:
+                        out << "lod(" << samplerReference << ", ";
+                        break;
+                    case TextureFunction::LOD0BIAS:
+                        out << "lod(" << samplerReference << ", ";
+                        break;
                   default: UNREACHABLE();
                 }
             }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
+            else if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
             {
                 if (textureFunction->method == TextureFunction::GRAD)
                 {
                     if (IsIntegerSampler(textureFunction->sampler))
                     {
-                        out << "x.Load(";
+                        out << "" << textureReference << ".Load(";
                     }
                     else if (IsShadowSampler(textureFunction->sampler))
                     {
-                        out << "x.SampleCmpLevelZero(s, ";
+                        out << "" << textureReference << ".SampleCmpLevelZero(" << samplerReference
+                            << ", ";
                     }
                     else
                     {
-                        out << "x.SampleGrad(s, ";
+                        out << "" << textureReference << ".SampleGrad(" << samplerReference << ", ";
                     }
                 }
                 else if (IsIntegerSampler(textureFunction->sampler) ||
                          textureFunction->method == TextureFunction::FETCH)
                 {
-                    out << "x.Load(";
+                    out << "" << textureReference << ".Load(";
                 }
                 else if (IsShadowSampler(textureFunction->sampler))
                 {
                     switch(textureFunction->method)
                     {
-                      case TextureFunction::IMPLICIT: out << "x.SampleCmp(s, ";          break;
-                      case TextureFunction::BIAS:     out << "x.SampleCmp(s, ";          break;
-                      case TextureFunction::LOD:      out << "x.SampleCmp(s, ";          break;
-                      case TextureFunction::LOD0:     out << "x.SampleCmpLevelZero(s, "; break;
-                      case TextureFunction::LOD0BIAS: out << "x.SampleCmpLevelZero(s, "; break;
+                        case TextureFunction::IMPLICIT:
+                            out << "" << textureReference << ".SampleCmp(" << samplerReference
+                                << ", ";
+                            break;
+                        case TextureFunction::BIAS:
+                            out << "" << textureReference << ".SampleCmp(" << samplerReference
+                                << ", ";
+                            break;
+                        case TextureFunction::LOD:
+                            out << "" << textureReference << ".SampleCmp(" << samplerReference
+                                << ", ";
+                            break;
+                        case TextureFunction::LOD0:
+                            out << "" << textureReference << ".SampleCmpLevelZero("
+                                << samplerReference << ", ";
+                            break;
+                        case TextureFunction::LOD0BIAS:
+                            out << "" << textureReference << ".SampleCmpLevelZero("
+                                << samplerReference << ", ";
+                            break;
                       default: UNREACHABLE();
                     }
                 }
                 else
                 {
                     switch(textureFunction->method)
                     {
-                      case TextureFunction::IMPLICIT: out << "x.Sample(s, ";      break;
-                      case TextureFunction::BIAS:     out << "x.SampleBias(s, ";  break;
-                      case TextureFunction::LOD:      out << "x.SampleLevel(s, "; break;
-                      case TextureFunction::LOD0:     out << "x.SampleLevel(s, "; break;
-                      case TextureFunction::LOD0BIAS: out << "x.SampleLevel(s, "; break;
+                        case TextureFunction::IMPLICIT:
+                            out << "" << textureReference << ".Sample(" << samplerReference << ", ";
+                            break;
+                        case TextureFunction::BIAS:
+                            out << "" << textureReference << ".SampleBias(" << samplerReference
+                                << ", ";
+                            break;
+                        case TextureFunction::LOD:
+                            out << "" << textureReference << ".SampleLevel(" << samplerReference
+                                << ", ";
+                            break;
+                        case TextureFunction::LOD0:
+                            out << "" << textureReference << ".SampleLevel(" << samplerReference
+                                << ", ";
+                            break;
+                        case TextureFunction::LOD0BIAS:
+                            out << "" << textureReference << ".SampleLevel(" << samplerReference
+                                << ", ";
+                            break;
                       default: UNREACHABLE();
                     }
                 }
             }
             else UNREACHABLE();
 
             // Integer sampling requires integer addresses
             TString addressx = "";
@@ -1170,17 +1236,17 @@ void OutputHLSL::header(TInfoSinkBase &o
                   case 3: proj = " / t.z"; break;
                   case 4: proj = " / t.w"; break;
                   default: UNREACHABLE();
                 }
             }
 
             out << addressx + ("t.x" + proj) + close + ", " + addressy + ("t.y" + proj) + close;
 
-            if (mOutputType == SH_HLSL9_OUTPUT)
+            if (mOutputType == SH_HLSL_3_0_OUTPUT)
             {
                 if (hlslCoords >= 3)
                 {
                     if (textureFunction->coords < 3)
                     {
                         out << ", 0";
                     }
                     else
@@ -1198,17 +1264,17 @@ void OutputHLSL::header(TInfoSinkBase &o
                       case TextureFunction::LOD0:     out << ", 0";    break;
                       case TextureFunction::LOD0BIAS: out << ", bias"; break;
                       default: UNREACHABLE();
                     }
                 }
 
                 out << "));\n";
             }
-            else if (mOutputType == SH_HLSL11_OUTPUT)
+            else if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
             {
                 if (hlslCoords >= 3)
                 {
                     if (IsIntegerSampler(textureFunction->sampler) && IsSamplerCube(textureFunction->sampler))
                     {
                         out << ", face";
                     }
                     else
@@ -2388,17 +2454,18 @@ bool OutputHLSL::visitAggregate(Visit vi
 
                 mUsesTexture.insert(textureFunction);
 
                 out << textureFunction.name();
             }
 
             for (TIntermSequence::iterator arg = arguments->begin(); arg != arguments->end(); arg++)
             {
-                if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType()))
+                if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT &&
+                    IsSampler((*arg)->getAsTyped()->getBasicType()))
                 {
                     out << "texture_";
                     (*arg)->traverse(this);
                     out << ", sampler_";
                 }
 
                 (*arg)->traverse(this);
 
@@ -2722,17 +2789,17 @@ bool OutputHLSL::visitLoop(Visit visit, 
     mNestedLoopDepth++;
 
     bool wasDiscontinuous = mInsideDiscontinuousLoop;
     mInsideDiscontinuousLoop = mInsideDiscontinuousLoop ||
     mCurrentFunctionMetadata->mDiscontinuousLoops.count(node) > 0;
 
     TInfoSinkBase &out = getInfoSink();
 
-    if (mOutputType == SH_HLSL9_OUTPUT)
+    if (mOutputType == SH_HLSL_3_0_OUTPUT)
     {
         if (handleExcessiveLoop(out, node))
         {
             mInsideDiscontinuousLoop = wasDiscontinuous;
             mNestedLoopDepth--;
 
             return false;
         }
@@ -3149,21 +3216,31 @@ TString OutputHLSL::argumentString(const
     {
         nameStr = "x" + str(mUniqueIndex++);
     }
     else
     {
         nameStr = DecorateIfNeeded(name);
     }
 
-    if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))
+    if (IsSampler(type.getBasicType()))
     {
-        return QualifierString(qualifier) + " " + TextureString(type) + " texture_" + nameStr +
-               ArrayString(type) + ", " + QualifierString(qualifier) + " " + SamplerString(type) +
-               " sampler_" + nameStr + ArrayString(type);
+        if (mOutputType == SH_HLSL_4_1_OUTPUT)
+        {
+            // Samplers are passed as indices to the sampler array.
+            ASSERT(qualifier != EvqOut && qualifier != EvqInOut);
+            return "const uint " + nameStr + ArrayString(type);
+        }
+        if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+        {
+            return QualifierString(qualifier) + " " + TextureString(type.getBasicType()) +
+                   " texture_" + nameStr + ArrayString(type) + ", " + QualifierString(qualifier) +
+                   " " + SamplerString(type.getBasicType()) + " sampler_" + nameStr +
+                   ArrayString(type);
+        }
     }
 
     return QualifierString(qualifier) + " " + TypeString(type) + " " + nameStr + ArrayString(type);
 }
 
 TString OutputHLSL::initializer(const TType &type)
 {
     TString string;
--- a/gfx/angle/src/compiler/translator/ParseContext.cpp
+++ b/gfx/angle/src/compiler/translator/ParseContext.cpp
@@ -1920,16 +1920,94 @@ void TParseContext::parseGlobalLayoutQua
     }
 
     if (layoutQualifier.blockStorage != EbsUnspecified)
     {
         mDefaultBlockStorage = layoutQualifier.blockStorage;
     }
 }
 
+TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function,
+                                                                 const TSourceLoc &location)
+{
+    // Note: symbolTableFunction could be the same as function if this is the first declaration.
+    // Either way the instance in the symbol table is used to track whether the function is declared
+    // multiple times.
+    TFunction *symbolTableFunction =
+        static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
+    if (symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
+    {
+        // ESSL 1.00.17 section 4.2.7.
+        // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
+        error(location, "duplicate function prototype declarations are not allowed", "function");
+        recover();
+    }
+    symbolTableFunction->setHasPrototypeDeclaration();
+
+    TIntermAggregate *prototype = new TIntermAggregate;
+    prototype->setType(function.getReturnType());
+    prototype->setName(function.getMangledName());
+    prototype->setFunctionId(function.getUniqueId());
+
+    for (size_t i = 0; i < function.getParamCount(); i++)
+    {
+        const TConstParameter &param = function.getParam(i);
+        if (param.name != 0)
+        {
+            TVariable variable(param.name, *param.type);
+
+            TIntermSymbol *paramSymbol = intermediate.addSymbol(
+                variable.getUniqueId(), variable.getName(), variable.getType(), location);
+            prototype = intermediate.growAggregate(prototype, paramSymbol, location);
+        }
+        else
+        {
+            TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
+            prototype                  = intermediate.growAggregate(prototype, paramSymbol, location);
+        }
+    }
+
+    prototype->setOp(EOpPrototype);
+
+    symbolTable.pop();
+
+    if (!symbolTable.atGlobalLevel())
+    {
+        // ESSL 3.00.4 section 4.2.4.
+        error(location, "local function prototype declarations are not allowed", "function");
+        recover();
+    }
+
+    return prototype;
+}
+
+TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function,
+                                                       TIntermAggregate *functionPrototype,
+                                                       TIntermAggregate *functionBody,
+                                                       const TSourceLoc &location)
+{
+    //?? Check that all paths return a value if return type != void ?
+    //   May be best done as post process phase on intermediate code
+    if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
+    {
+        error(location, "function does not return a value:", "", function.getName().c_str());
+        recover();
+    }
+
+    TIntermAggregate *aggregate =
+        intermediate.growAggregate(functionPrototype, functionBody, location);
+    intermediate.setAggregateOperator(aggregate, EOpFunction, location);
+    aggregate->setName(function.getMangledName().c_str());
+    aggregate->setType(function.getReturnType());
+    aggregate->setFunctionId(function.getUniqueId());
+
+    symbolTable.pop();
+    return aggregate;
+}
+
 void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
                                            TFunction *function,
                                            TIntermAggregate **aggregateOut)
 {
     const TSymbol *builtIn =
         symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
 
     if (builtIn)
@@ -1973,18 +2051,18 @@ void TParseContext::parseFunctionPrototy
                   "main function cannot return a value");
             recover();
         }
     }
 
     //
     // Remember the return type for later checking for RETURN statements.
     //
-    setCurrentFunctionType(&(prevDec->getReturnType()));
-    setFunctionReturnsValue(false);
+    mCurrentFunctionType  = &(prevDec->getReturnType());
+    mFunctionReturnsValue = false;
 
     //
     // Insert parameters into the symbol table.
     // If the parameter has no name, it's not an error, just don't insert it
     // (could be used for unused args).
     //
     // Also, accumulate the list of parameters into the HIL, so lower level code
     // knows where to find parameters.
@@ -2025,22 +2103,22 @@ void TParseContext::parseFunctionPrototy
     intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
     *aggregateOut = paramNodes;
     setLoopNestingLevel(0);
 }
 
 TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
 {
     //
-    // Multiple declarations of the same function are allowed.
+    // We don't know at this point whether this is a function definition or a prototype.
+    // The definition production code will check for redefinitions.
+    // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
     //
-    // If this is a definition, the definition production code will check for redefinitions
-    // (we don't know at this point if it's a definition or not).
-    //
-    // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
+    // Return types and parameter qualifiers must match in all redeclarations, so those are checked
+    // here.
     //
     TFunction *prevDec =
         static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
     if (prevDec)
     {
         if (prevDec->getReturnType() != function->getReturnType())
         {
             error(location, "overloaded functions must have the same return type",
--- a/gfx/angle/src/compiler/translator/ParseContext.h
+++ b/gfx/angle/src/compiler/translator/ParseContext.h
@@ -52,16 +52,17 @@ class TParseContext : angle::NonCopyable
           mChecksPrecisionErrors(checksPrecErrors),
           mFragmentPrecisionHighOnESSL1(false),
           mDefaultMatrixPacking(EmpColumnMajor),
           mDefaultBlockStorage(EbsShared),
           mDiagnostics(is),
           mDirectiveHandler(ext,
                             mDiagnostics,
                             mShaderVersion,
+                            mShaderType,
                             resources.WEBGL_debug_shader_precision == 1),
           mPreprocessor(&mDiagnostics, &mDirectiveHandler),
           mScanner(nullptr),
           mUsesFragData(false),
           mUsesFragColor(false),
           mUsesSecondaryOutputs(false),
           mMinProgramTexelOffset(resources.MinProgramTexelOffset),
           mMaxProgramTexelOffset(resources.MaxProgramTexelOffset)
@@ -97,33 +98,21 @@ class TParseContext : angle::NonCopyable
     {
         return mFragmentPrecisionHighOnESSL1 || mShaderVersion >= 300;
     }
     void setFragmentPrecisionHighOnESSL1(bool fragmentPrecisionHigh)
     {
         mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh;
     }
 
-    bool getFunctionReturnsValue() const { return mFunctionReturnsValue; }
-    void setFunctionReturnsValue(bool functionReturnsValue)
-    {
-        mFunctionReturnsValue = functionReturnsValue;
-    }
-
     void setLoopNestingLevel(int loopNestintLevel)
     {
         mLoopNestingLevel = loopNestintLevel;
     }
 
-    const TType *getCurrentFunctionType() const { return mCurrentFunctionType; }
-    void setCurrentFunctionType(const TType *currentFunctionType)
-    {
-        mCurrentFunctionType = currentFunctionType;
-    }
-
     void incrLoopNestingLevel() { ++mLoopNestingLevel; }
     void decrLoopNestingLevel() { --mLoopNestingLevel; }
 
     void incrSwitchNestingLevel() { ++mSwitchNestingLevel; }
     void decrSwitchNestingLevel() { --mSwitchNestingLevel; }
 
     // This method is guaranteed to succeed, even if no variable with 'name' exists.
     const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol);
@@ -239,16 +228,22 @@ class TParseContext : angle::NonCopyable
                                                const TSourceLoc &identifierLocation,
                                                const TString &identifier,
                                                const TSourceLoc &indexLocation,
                                                TIntermTyped *indexExpression,
                                                const TSourceLoc &initLocation,
                                                TIntermTyped *initializer);
 
     void parseGlobalLayoutQualifier(const TPublicType &typeQualifier);
+    TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &function,
+                                                      const TSourceLoc &location);
+    TIntermAggregate *addFunctionDefinition(const TFunction &function,
+                                            TIntermAggregate *functionPrototype,
+                                            TIntermAggregate *functionBody,
+                                            const TSourceLoc &location);
     void parseFunctionPrototype(const TSourceLoc &location,
                                 TFunction *function,
                                 TIntermAggregate **aggregateOut);
     TFunction *parseFunctionDeclarator(const TSourceLoc &location,
                                        TFunction *function);
     TFunction *addConstructorFunc(const TPublicType &publicType);
     TIntermTyped *addConstructor(TIntermNode *arguments,
                                  TType *type,
--- a/gfx/angle/src/compiler/translator/ShaderLang.cpp
+++ b/gfx/angle/src/compiler/translator/ShaderLang.cpp
@@ -184,19 +184,26 @@ void ShInitBuiltInResources(ShBuiltInRes
 //
 // Driver calls these to create and destroy compiler objects.
 //
 ShHandle ShConstructCompiler(sh::GLenum type, ShShaderSpec spec,
                              ShShaderOutput output,
                              const ShBuiltInResources* resources)
 {
     TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
+    if (base == nullptr)
+    {
+        return 0;
+    }
+
     TCompiler* compiler = base->getAsCompiler();
-    if (compiler == 0)
+    if (compiler == nullptr)
+    {
         return 0;
+    }
 
     // Generate built-in symbol table.
     if (!compiler->Init(*resources)) {
         ShDestruct(base);
         return 0;
     }
 
     return reinterpret_cast<void*>(base);
--- a/gfx/angle/src/compiler/translator/ShaderVars.cpp
+++ b/gfx/angle/src/compiler/translator/ShaderVars.cpp
@@ -388,9 +388,14 @@ InterfaceBlock &InterfaceBlock::operator
     arraySize = other.arraySize;
     layout = other.layout;
     isRowMajorLayout = other.isRowMajorLayout;
     staticUse = other.staticUse;
     fields = other.fields;
     return *this;
 }
 
+std::string InterfaceBlock::fieldPrefix() const
+{
+    return instanceName.empty() ? "" : name;
 }
+
+}  // namespace sh
--- a/gfx/angle/src/compiler/translator/SymbolTable.h
+++ b/gfx/angle/src/compiler/translator/SymbolTable.h
@@ -192,22 +192,26 @@ struct TParameter
     TString *name;
     TType *type;
 };
 
 // The function sub-class of a symbol.  
 class TFunction : public TSymbol
 {
   public:
-    TFunction(const TString *name, const TType *retType, TOperator tOp = EOpNull, const char *ext = "")
+    TFunction(const TString *name,
+              const TType *retType,
+              TOperator tOp   = EOpNull,
+              const char *ext = "")
         : TSymbol(name),
           returnType(retType),
           mangledName(nullptr),
           op(tOp),
-          defined(false)
+          defined(false),
+          mHasPrototypeDeclaration(false)
     {
         relateToExtension(ext);
     }
     ~TFunction() override;
     bool isFunction() const override { return true; }
 
     static TString mangleName(const TString &name)
     {
@@ -237,24 +241,20 @@ class TFunction : public TSymbol
         return *returnType;
     }
 
     TOperator getBuiltInOp() const
     {
         return op;
     }
 
-    void setDefined()
-    {
-        defined = true;
-    }
-    bool isDefined()
-    {
-        return defined;
-    }
+    void setDefined() { defined = true; }
+    bool isDefined() { return defined; }
+    void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; }
+    bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
 
     size_t getParamCount() const
     {
         return parameters.size();
     }
     const TConstParameter &getParam(size_t i) const
     {
         return parameters[i];
@@ -264,16 +264,17 @@ class TFunction : public TSymbol
     const TString *buildMangledName() const;
 
     typedef TVector<TConstParameter> TParamList;
     TParamList parameters;
     const TType *returnType;
     mutable const TString *mangledName;
     TOperator op;
     bool defined;
+    bool mHasPrototypeDeclaration;
 };
 
 // Interface block name sub-symbol
 class TInterfaceBlockName : public TSymbol
 {
   public:
     TInterfaceBlockName(const TString *name)
         : TSymbol(name)
--- a/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp
@@ -42,17 +42,17 @@ void TranslatorHLSL::translate(TIntermNo
     if (!shouldRunLoopAndIndexingValidation(compileOptions))
     {
         // HLSL doesn't support dynamic indexing of vectors and matrices.
         RemoveDynamicIndexing(root, getTemporaryIndex(), getSymbolTable(), getShaderVersion());
     }
 
     // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
     // use a vertex attribute as a condition, and some related computation in the else block.
-    if (getOutputType() == SH_HLSL9_OUTPUT && getShaderType() == GL_VERTEX_SHADER)
+    if (getOutputType() == SH_HLSL_3_0_OUTPUT && getShaderType() == GL_VERTEX_SHADER)
     {
         sh::RewriteElseBlocks(root, getTemporaryIndex());
     }
 
     sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
         getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), compileOptions);
 
     outputHLSL.output(root, getInfoSink().obj);
--- a/gfx/angle/src/compiler/translator/UniformHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/UniformHLSL.cpp
@@ -88,77 +88,167 @@ const Uniform *UniformHLSL::findUniformB
             return &mUniforms[uniformIndex];
         }
     }
 
     UNREACHABLE();
     return NULL;
 }
 
-unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
+unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type,
+                                                          const TString &name,
+                                                          unsigned int *registerCount)
 {
     unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
 
     const Uniform *uniform = findUniformByName(name);
     ASSERT(uniform);
 
     mUniformRegisterMap[uniform->name] = registerIndex;
 
-    unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
+    ASSERT(registerCount);
+    *registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
 
     if (gl::IsSamplerType(uniform->type))
     {
-        mSamplerRegister += registerCount;
+        mSamplerRegister += *registerCount;
     }
     else
     {
-        mUniformRegister += registerCount;
+        mUniformRegister += *registerCount;
     }
 
     return registerIndex;
 }
 
-TString UniformHLSL::uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms)
+unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
 {
-    TString uniforms;
+    unsigned int registerCount;
+    return declareUniformAndAssignRegister(type, name, &registerCount);
+}
 
-    for (ReferencedSymbols::const_iterator uniformIt = referencedUniforms.begin();
-         uniformIt != referencedUniforms.end(); uniformIt++)
+void UniformHLSL::outputHLSLSamplerUniformGroup(TInfoSinkBase &out,
+                                                const HLSLTextureSamplerGroup textureGroup,
+                                                const TVector<const TIntermSymbol *> &group,
+                                                unsigned int *groupTextureRegisterIndex)
+{
+    if (group.empty())
+    {
+        return;
+    }
+    unsigned int groupRegisterCount = 0;
+    for (const TIntermSymbol *uniform : group)
     {
-        const TIntermSymbol &uniform = *uniformIt->second;
+        const TType &type   = uniform->getType();
+        const TString &name = uniform->getSymbol();
+        unsigned int registerCount;
+        unsigned int samplerArrayIndex =
+            declareUniformAndAssignRegister(type, name, &registerCount);
+        groupRegisterCount += registerCount;
+        if (type.isArray())
+        {
+            out << "static const uint " << DecorateIfNeeded(uniform->getName()) << ArrayString(type)
+                << " = {";
+            for (int i = 0; i < type.getArraySize(); ++i)
+            {
+                if (i > 0)
+                    out << ", ";
+                out << (samplerArrayIndex + i);
+            }
+            out << "};\n";
+        }
+        else
+        {
+            out << "static const uint " << DecorateIfNeeded(uniform->getName()) << " = "
+                << samplerArrayIndex << ";\n";
+        }
+    }
+    TString suffix = TextureGroupSuffix(textureGroup);
+    // Since HLSL_TEXTURE_2D is the first group, it has a fixed offset of zero.
+    if (textureGroup != HLSL_TEXTURE_2D)
+    {
+        out << "static const uint textureIndexOffset" << suffix << " = "
+            << (*groupTextureRegisterIndex) << ";\n";
+        out << "static const uint samplerIndexOffset" << suffix << " = "
+            << (*groupTextureRegisterIndex) << ";\n";
+    }
+    out << "uniform " << TextureString(textureGroup) << " textures" << suffix << "["
+        << groupRegisterCount << "]"
+        << " : register(t" << (*groupTextureRegisterIndex) << ");\n";
+    out << "uniform " << SamplerString(textureGroup) << " samplers" << suffix << "["
+        << groupRegisterCount << "]"
+        << " : register(s" << (*groupTextureRegisterIndex) << ");\n";
+    *groupTextureRegisterIndex += groupRegisterCount;
+}
+
+void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
+                                 ShShaderOutput outputType,
+                                 const ReferencedSymbols &referencedUniforms)
+{
+    if (!referencedUniforms.empty())
+    {
+        out << "// Uniforms\n\n";
+    }
+    // In the case of HLSL 4, sampler uniforms need to be grouped by type before the code is
+    // written. They are grouped based on the combination of the HLSL texture type and
+    // HLSL sampler type, enumerated in HLSLTextureSamplerGroup.
+    TVector<TVector<const TIntermSymbol *>> groupedSamplerUniforms;
+    groupedSamplerUniforms.resize(HLSL_TEXTURE_MAX + 1);
+    for (auto &uniformIt : referencedUniforms)
+    {
+        // Output regular uniforms. Group sampler uniforms by type.
+        const TIntermSymbol &uniform = *uniformIt.second;
         const TType &type = uniform.getType();
         const TString &name = uniform.getSymbol();
 
-        unsigned int registerIndex = declareUniformAndAssignRegister(type, name);
-
-        if (outputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))   // Also declare the texture
+        if (outputType == SH_HLSL_4_1_OUTPUT && IsSampler(type.getBasicType()))
+        {
+            HLSLTextureSamplerGroup group = TextureGroup(type.getBasicType());
+            groupedSamplerUniforms[group].push_back(&uniform);
+        }
+        else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(type.getBasicType()))
         {
-            uniforms += "uniform " + SamplerString(type) + " sampler_" + DecorateUniform(name, type) + ArrayString(type) +
-                        " : register(s" + str(registerIndex) + ");\n";
-
-            uniforms += "uniform " + TextureString(type) + " texture_" + DecorateUniform(name, type) + ArrayString(type) +
-                        " : register(t" + str(registerIndex) + ");\n";
+            unsigned int registerIndex = declareUniformAndAssignRegister(type, name);
+            out << "uniform " << SamplerString(type.getBasicType()) << " sampler_"
+                << DecorateUniform(name, type) << ArrayString(type) << " : register(s"
+                << str(registerIndex) << ");\n";
+            out << "uniform " << TextureString(type.getBasicType()) << " texture_"
+                << DecorateUniform(name, type) << ArrayString(type) << " : register(t"
+                << str(registerIndex) << ");\n";
         }
         else
         {
+            unsigned int registerIndex  = declareUniformAndAssignRegister(type, name);
             const TStructure *structure = type.getStruct();
             // If this is a nameless struct, we need to use its full definition, rather than its (empty) name.
             // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for 
             // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers are
             // permitted.
             const TString &typeName = ((structure && !structure->name().empty()) ?
                                         QualifiedStructNameString(*structure, false, false) : TypeString(type));
 
             const TString &registerString = TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")";
 
-            uniforms += "uniform " + typeName + " " + DecorateUniform(name, type) + ArrayString(type) + " : " + registerString + ";\n";
+            out << "uniform " << typeName << " " << DecorateUniform(name, type) << ArrayString(type)
+                << " : " << registerString << ";\n";
         }
     }
 
-    return (uniforms.empty() ? "" : ("// Uniforms\n\n" + uniforms));
+    if (outputType == SH_HLSL_4_1_OUTPUT)
+    {
+        unsigned int groupTextureRegisterIndex = 0;
+        // TEXTURE_2D is special, index offset is assumed to be 0 and omitted in that case.
+        ASSERT(HLSL_TEXTURE_MIN == HLSL_TEXTURE_2D);
+        for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId)
+        {
+            outputHLSLSamplerUniformGroup(out, HLSLTextureSamplerGroup(groupId),
+                                          groupedSamplerUniforms[groupId],
+                                          &groupTextureRegisterIndex);
+        }
+    }
 }
 
 TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
 {
     TString interfaceBlocks;
 
     for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin();
          interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++)
--- a/gfx/angle/src/compiler/translator/UniformHLSL.h
+++ b/gfx/angle/src/compiler/translator/UniformHLSL.h
@@ -6,29 +6,36 @@
 // UniformHLSL.h:
 //   Methods for GLSL to HLSL translation for uniforms and interface blocks.
 //
 
 #ifndef COMPILER_TRANSLATOR_UNIFORMHLSL_H_
 #define COMPILER_TRANSLATOR_UNIFORMHLSL_H_
 
 #include "compiler/translator/OutputHLSL.h"
+#include "compiler/translator/UtilsHLSL.h"
 
 namespace sh
 {
 class StructureHLSL;
 
 class UniformHLSL : angle::NonCopyable
 {
   public:
     UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector<Uniform> &uniforms);
 
     void reserveUniformRegisters(unsigned int registerCount);
     void reserveInterfaceBlockRegisters(unsigned int registerCount);
-    TString uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms);
+    void outputHLSLSamplerUniformGroup(TInfoSinkBase &out,
+                                       const HLSLTextureSamplerGroup textureGroup,
+                                       const TVector<const TIntermSymbol *> &group,
+                                       unsigned int *groupTextureRegisterIndex);
+    void uniformsHeader(TInfoSinkBase &out,
+                        ShShaderOutput outputType,
+                        const ReferencedSymbols &referencedUniforms);
     TString interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks);
 
     // Used for direct index references
     static TString interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex);
 
     const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const
     {
         return mInterfaceBlockRegisterMap;
@@ -40,16 +47,19 @@ class UniformHLSL : angle::NonCopyable
 
   private:
     TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex);
     TString interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage);
     TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock);
     const Uniform *findUniformByName(const TString &name) const;
 
     // Returns the uniform's register index
+    unsigned int declareUniformAndAssignRegister(const TType &type,
+                                                 const TString &name,
+                                                 unsigned int *registerCount);
     unsigned int declareUniformAndAssignRegister(const TType &type, const TString &name);
 
     unsigned int mUniformRegister;
     unsigned int mInterfaceBlockRegister;
     unsigned int mSamplerRegister;
     StructureHLSL *mStructureHLSL;
     ShShaderOutput mOutputType;
 
--- a/gfx/angle/src/compiler/translator/UtilsHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/UtilsHLSL.cpp
@@ -10,54 +10,180 @@
 #include "compiler/translator/UtilsHLSL.h"
 #include "compiler/translator/IntermNode.h"
 #include "compiler/translator/StructureHLSL.h"
 #include "compiler/translator/SymbolTable.h"
 
 namespace sh
 {
 
-TString SamplerString(const TType &type)
+TString SamplerString(const TBasicType type)
 {
-    if (IsShadowSampler(type.getBasicType()))
+    if (IsShadowSampler(type))
+    {
+        return "SamplerComparisonState";
+    }
+    else
+    {
+        return "SamplerState";
+    }
+}
+
+TString SamplerString(HLSLTextureSamplerGroup type)
+{
+    if (type >= HLSL_COMPARISON_SAMPLER_GROUP_BEGIN && type <= HLSL_COMPARISON_SAMPLER_GROUP_END)
     {
         return "SamplerComparisonState";
     }
     else
     {
         return "SamplerState";
     }
 }
 
-TString TextureString(const TType &type)
+HLSLTextureSamplerGroup TextureGroup(const TBasicType type)
 {
-    switch (type.getBasicType())
+    switch (type)
     {
-      case EbtSampler2D:            return "Texture2D";
-      case EbtSamplerCube:          return "TextureCube";
-      case EbtSamplerExternalOES:   return "Texture2D";
-      case EbtSampler2DArray:       return "Texture2DArray";
-      case EbtSampler3D:            return "Texture3D";
-      case EbtISampler2D:           return "Texture2D<int4>";
-      case EbtISampler3D:           return "Texture3D<int4>";
-      case EbtISamplerCube:         return "Texture2DArray<int4>";
-      case EbtISampler2DArray:      return "Texture2DArray<int4>";
-      case EbtUSampler2D:           return "Texture2D<uint4>";
-      case EbtUSampler3D:           return "Texture3D<uint4>";
-      case EbtUSamplerCube:         return "Texture2DArray<uint4>";
-      case EbtUSampler2DArray:      return "Texture2DArray<uint4>";
-      case EbtSampler2DShadow:      return "Texture2D";
-      case EbtSamplerCubeShadow:    return "TextureCube";
-      case EbtSampler2DArrayShadow: return "Texture2DArray";
-      default: UNREACHABLE();
+        case EbtSampler2D:
+            return HLSL_TEXTURE_2D;
+        case EbtSamplerCube:
+            return HLSL_TEXTURE_CUBE;
+        case EbtSamplerExternalOES:
+            return HLSL_TEXTURE_2D;
+        case EbtSampler2DArray:
+            return HLSL_TEXTURE_2D_ARRAY;
+        case EbtSampler3D:
+            return HLSL_TEXTURE_3D;
+        case EbtISampler2D:
+            return HLSL_TEXTURE_2D_INT4;
+        case EbtISampler3D:
+            return HLSL_TEXTURE_3D_INT4;
+        case EbtISamplerCube:
+            return HLSL_TEXTURE_2D_ARRAY_INT4;
+        case EbtISampler2DArray:
+            return HLSL_TEXTURE_2D_ARRAY_INT4;
+        case EbtUSampler2D:
+            return HLSL_TEXTURE_2D_UINT4;
+        case EbtUSampler3D:
+            return HLSL_TEXTURE_3D_UINT4;
+        case EbtUSamplerCube:
+            return HLSL_TEXTURE_2D_ARRAY_UINT4;
+        case EbtUSampler2DArray:
+            return HLSL_TEXTURE_2D_ARRAY_UINT4;
+        case EbtSampler2DShadow:
+            return HLSL_TEXTURE_2D_COMPARISON;
+        case EbtSamplerCubeShadow:
+            return HLSL_TEXTURE_CUBE_COMPARISON;
+        case EbtSampler2DArrayShadow:
+            return HLSL_TEXTURE_2D_ARRAY_COMPARISON;
+        default:
+            UNREACHABLE();
+    }
+    return HLSL_TEXTURE_UNKNOWN;
+}
+
+TString TextureString(const HLSLTextureSamplerGroup type)
+{
+    switch (type)
+    {
+        case HLSL_TEXTURE_2D:
+            return "Texture2D";
+        case HLSL_TEXTURE_CUBE:
+            return "TextureCube";
+        case HLSL_TEXTURE_2D_ARRAY:
+            return "Texture2DArray";
+        case HLSL_TEXTURE_3D:
+            return "Texture3D";
+        case HLSL_TEXTURE_2D_INT4:
+            return "Texture2D<int4>";
+        case HLSL_TEXTURE_3D_INT4:
+            return "Texture3D<int4>";
+        case HLSL_TEXTURE_2D_ARRAY_INT4:
+            return "Texture2DArray<int4>";
+        case HLSL_TEXTURE_2D_UINT4:
+            return "Texture2D<uint4>";
+        case HLSL_TEXTURE_3D_UINT4:
+            return "Texture3D<uint4>";
+        case HLSL_TEXTURE_2D_ARRAY_UINT4:
+            return "Texture2DArray<uint4>";
+        case HLSL_TEXTURE_2D_COMPARISON:
+            return "Texture2D";
+        case HLSL_TEXTURE_CUBE_COMPARISON:
+            return "TextureCube";
+        case HLSL_TEXTURE_2D_ARRAY_COMPARISON:
+            return "Texture2DArray";
+        default:
+            UNREACHABLE();
     }
 
     return "<unknown texture type>";
 }
 
+TString TextureString(const TBasicType type)
+{
+    return TextureString(TextureGroup(type));
+}
+
+TString TextureGroupSuffix(const HLSLTextureSamplerGroup type)
+{
+    switch (type)
+    {
+        case HLSL_TEXTURE_2D:
+            return "2D";
+        case HLSL_TEXTURE_CUBE:
+            return "Cube";
+        case HLSL_TEXTURE_2D_ARRAY:
+            return "2DArray";
+        case HLSL_TEXTURE_3D:
+            return "3D";
+        case HLSL_TEXTURE_2D_INT4:
+            return "2D_int4_";
+        case HLSL_TEXTURE_3D_INT4:
+            return "3D_int4_";
+        case HLSL_TEXTURE_2D_ARRAY_INT4:
+            return "2DArray_int4_";
+        case HLSL_TEXTURE_2D_UINT4:
+            return "2D_uint4_";
+        case HLSL_TEXTURE_3D_UINT4:
+            return "3D_uint4_";
+        case HLSL_TEXTURE_2D_ARRAY_UINT4:
+            return "2DArray_uint4_";
+        case HLSL_TEXTURE_2D_COMPARISON:
+            return "2D_comparison";
+        case HLSL_TEXTURE_CUBE_COMPARISON:
+            return "Cube_comparison";
+        case HLSL_TEXTURE_2D_ARRAY_COMPARISON:
+            return "2DArray_comparison";
+        default:
+            UNREACHABLE();
+    }
+
+    return "<unknown texture type>";
+}
+
+TString TextureGroupSuffix(const TBasicType type)
+{
+    return TextureGroupSuffix(TextureGroup(type));
+}
+
+TString TextureTypeSuffix(const TBasicType type)
+{
+    switch (type)
+    {
+        case EbtISamplerCube:
+            return "Cube_int4_";
+        case EbtUSamplerCube:
+            return "Cube_uint4_";
+        default:
+            // All other types are identified by their group suffix
+            return TextureGroupSuffix(type);
+    }
+}
+
 TString DecorateUniform(const TString &string, const TType &type)
 {
     if (type.getBasicType() == EbtSamplerExternalOES)
     {
         return "ex_" + string;
     }
 
     return Decorate(string);
@@ -265,9 +391,48 @@ TString QualifierString(TQualifier quali
       case EvqInOut:         return "inout";
       case EvqConstReadOnly: return "const";
       default: UNREACHABLE();
     }
 
     return "";
 }
 
+int HLSLTextureCoordsCount(const TBasicType samplerType)
+{
+    switch (samplerType)
+    {
+        case EbtSampler2D:
+            return 2;
+        case EbtSampler3D:
+            return 3;
+        case EbtSamplerCube:
+            return 3;
+        case EbtSampler2DArray:
+            return 3;
+        case EbtISampler2D:
+            return 2;
+        case EbtISampler3D:
+            return 3;
+        case EbtISamplerCube:
+            return 3;
+        case EbtISampler2DArray:
+            return 3;
+        case EbtUSampler2D:
+            return 2;
+        case EbtUSampler3D:
+            return 3;
+        case EbtUSamplerCube:
+            return 3;
+        case EbtUSampler2DArray:
+            return 3;
+        case EbtSampler2DShadow:
+            return 2;
+        case EbtSamplerCubeShadow:
+            return 3;
+        case EbtSampler2DArrayShadow:
+            return 3;
+        default:
+            UNREACHABLE();
+    }
+    return 0;
 }
+}
--- a/gfx/angle/src/compiler/translator/UtilsHLSL.h
+++ b/gfx/angle/src/compiler/translator/UtilsHLSL.h
@@ -15,28 +15,64 @@
 
 #include "angle_gl.h"
 
 class TName;
 
 namespace sh
 {
 
-TString TextureString(const TType &type);
-TString SamplerString(const TType &type);
+// Unique combinations of HLSL Texture type and HLSL Sampler type.
+enum HLSLTextureSamplerGroup
+{
+    // Regular samplers
+    HLSL_TEXTURE_2D,
+    HLSL_TEXTURE_MIN = HLSL_TEXTURE_2D,
+
+    HLSL_TEXTURE_CUBE,
+    HLSL_TEXTURE_2D_ARRAY,
+    HLSL_TEXTURE_3D,
+    HLSL_TEXTURE_2D_INT4,
+    HLSL_TEXTURE_3D_INT4,
+    HLSL_TEXTURE_2D_ARRAY_INT4,
+    HLSL_TEXTURE_2D_UINT4,
+    HLSL_TEXTURE_3D_UINT4,
+    HLSL_TEXTURE_2D_ARRAY_UINT4,
+
+    // Comparison samplers
+
+    HLSL_TEXTURE_2D_COMPARISON,
+    HLSL_TEXTURE_CUBE_COMPARISON,
+    HLSL_TEXTURE_2D_ARRAY_COMPARISON,
+
+    HLSL_COMPARISON_SAMPLER_GROUP_BEGIN = HLSL_TEXTURE_2D_COMPARISON,
+    HLSL_COMPARISON_SAMPLER_GROUP_END   = HLSL_TEXTURE_2D_ARRAY_COMPARISON,
+
+    HLSL_TEXTURE_UNKNOWN,
+    HLSL_TEXTURE_MAX = HLSL_TEXTURE_UNKNOWN
+};
+
+HLSLTextureSamplerGroup TextureGroup(const TBasicType type);
+TString TextureString(const HLSLTextureSamplerGroup type);
+TString TextureString(const TBasicType type);
+TString TextureGroupSuffix(const HLSLTextureSamplerGroup type);
+TString TextureGroupSuffix(const TBasicType type);
+TString TextureTypeSuffix(const TBasicType type);
+TString SamplerString(const TBasicType type);
+TString SamplerString(HLSLTextureSamplerGroup type);
 // Prepends an underscore to avoid naming clashes
 TString Decorate(const TString &string);
 TString DecorateIfNeeded(const TName &name);
 // Decorates and also unmangles the function name
 TString DecorateFunctionIfNeeded(const TName &name);
 TString DecorateUniform(const TString &string, const TType &type);
 TString DecorateField(const TString &string, const TStructure &structure);
 TString DecoratePrivate(const TString &privateText);
 TString TypeString(const TType &type);
 TString StructNameString(const TStructure &structure);
 TString QualifiedStructNameString(const TStructure &structure, bool useHLSLRowMajorPacking,
                                   bool useStd140Packing);
 TString InterpolationString(TQualifier qualifier);
 TString QualifierString(TQualifier qualifier);
-
+int HLSLTextureCoordsCount(const TBasicType samplerType);
 }
 
 #endif // COMPILER_TRANSLATOR_UTILSHLSL_H_
--- a/gfx/angle/src/compiler/translator/VariableInfo.cpp
+++ b/gfx/angle/src/compiler/translator/VariableInfo.cpp
@@ -11,28 +11,16 @@
 #include "common/utilities.h"
 
 namespace sh
 {
 
 namespace
 {
 
-TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field)
-{
-    if (interfaceBlock.hasInstanceName())
-    {
-        return interfaceBlock.name() + "." + field.name();
-    }
-    else
-    {
-        return field.name();
-    }
-}
-
 BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
 {
     switch (blockStorage)
     {
       case EbsPacked:         return BLOCKLAYOUT_PACKED;
       case EbsShared:         return BLOCKLAYOUT_SHARED;
       case EbsStd140:         return BLOCKLAYOUT_STANDARD;
       default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
@@ -554,26 +542,22 @@ void CollectVariables::visitVariable(con
     interfaceBlock.mappedName =
         TIntermTraverser::hash(blockType->name().c_str(), mHashFunction).c_str();
     interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
     interfaceBlock.arraySize = variable->getArraySize();
     interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
     interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
 
     // Gather field information
-    const TFieldList &fieldList = blockType->fields();
-
-    for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex)
+    for (const TField *field : blockType->fields())
     {
-        const TField &field = *fieldList[fieldIndex];
-        const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field);
-        const TType &fieldType = *field.type();
+        const TType &fieldType = *field->type();
 
         NameHashingTraverser traverser(mHashFunction, mSymbolTable);
-        traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields);
+        traverser.traverse(fieldType, field->name(), &interfaceBlock.fields);
 
         interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
     }
 
     infoList->push_back(interfaceBlock);
 }
 
 template <typename VarT>
--- a/gfx/angle/src/compiler/translator/blocklayout.h
+++ b/gfx/angle/src/compiler/translator/blocklayout.h
@@ -50,18 +50,16 @@ class COMPILER_EXPORT BlockLayoutEncoder
 {
   public:
     BlockLayoutEncoder();
     virtual ~BlockLayoutEncoder() {}
 
     BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix);
 
     size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
-    size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; }
-    size_t getCurrentElement() const { return mCurrentOffset % ComponentsPerRegister; }
 
     virtual void enterAggregateType() = 0;
     virtual void exitAggregateType() = 0;
 
     static const size_t BytesPerComponent = 4u;
     static const unsigned int ComponentsPerRegister = 4u;
 
     static size_t getBlockRegister(const BlockMemberInfo &info);
--- a/gfx/angle/src/compiler/translator/blocklayoutHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/blocklayoutHLSL.cpp
@@ -108,19 +108,24 @@ void HLSLBlockEncoder::skipRegisters(uns
 {
     mCurrentOffset += (numRegisters * ComponentsPerRegister);
 }
 
 HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType)
 {
     switch (outputType)
     {
-      case SH_HLSL9_OUTPUT: return ENCODE_LOOSE;
-      case SH_HLSL11_OUTPUT: return ENCODE_PACKED;
-      default: UNREACHABLE(); return ENCODE_PACKED;
+        case SH_HLSL_3_0_OUTPUT:
+            return ENCODE_LOOSE;
+        case SH_HLSL_4_1_OUTPUT:
+        case SH_HLSL_4_0_FL9_3_OUTPUT:
+            return ENCODE_PACKED;
+        default:
+            UNREACHABLE();
+            return ENCODE_PACKED;
     }
 }
 
 template <class ShaderVarType>
 void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
 {
     if (variable.isStruct())
     {
--- a/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h
+++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraph.h
@@ -137,37 +137,21 @@ public:
 // This class (and nobody else) manages the memory of the created nodes.
 // Nodes may not be removed after being added, so all created nodes will exist while the
 // TDependencyGraph instance exists.
 //
 class TDependencyGraph {
 public:
     TDependencyGraph(TIntermNode* intermNode);
     ~TDependencyGraph();
-    TGraphNodeVector::const_iterator begin() const { return mAllNodes.begin(); }
-    TGraphNodeVector::const_iterator end() const { return mAllNodes.end(); }
-
-    TGraphSymbolVector::const_iterator beginSamplerSymbols() const
-    {
-        return mSamplerSymbols.begin();
-    }
-
-    TGraphSymbolVector::const_iterator endSamplerSymbols() const
+    const TGraphNodeVector &allNodes() const { return mAllNodes; }
+    const TGraphSymbolVector &samplerSymbols() const { return mSamplerSymbols; }
+    const TFunctionCallVector &userDefinedFunctionCalls() const
     {
-        return mSamplerSymbols.end();
-    }
-
-    TFunctionCallVector::const_iterator beginUserDefinedFunctionCalls() const
-    {
-        return mUserDefinedFunctionCalls.begin();
-    }
-
-    TFunctionCallVector::const_iterator endUserDefinedFunctionCalls() const
-    {
-        return mUserDefinedFunctionCalls.end();
+        return mUserDefinedFunctionCalls;
     }
 
     TGraphArgument* createArgument(TIntermAggregate* intermFunctionCall, int argumentNumber);
     TGraphFunctionCall* createFunctionCall(TIntermAggregate* intermFunctionCall);
     TGraphSymbol* getOrCreateSymbol(TIntermSymbol* intermSymbol);
     TGraphSelection* createSelection(TIntermSelection* intermSelection);
     TGraphLoop* createLoop(TIntermLoop* intermLoop);
     TGraphLogicalOp* createLogicalOp(TIntermBinary* intermLogicalOp);
--- a/gfx/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp
+++ b/gfx/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp
@@ -49,17 +49,16 @@ void TDependencyGraphOutput::visitLogica
     outputIndentation();
     mSink << "logical " << logicalOp->getOpString() << "\n";
 }
 
 void TDependencyGraphOutput::outputAllSpanningTrees(TDependencyGraph& graph)
 {
     mSink << "\n";
 
-    for (TGraphNodeVector::const_iterator iter = graph.begin(); iter != graph.end(); ++iter)
+    for (auto symbol : graph.allNodes())
     {
-        TGraphNode* symbol = *iter;
         mSink << "--- Dependency graph spanning tree ---\n";
         clearVisited();
         symbol->traverse(this);
         mSink << "\n";
     }
 }
--- a/gfx/angle/src/compiler/translator/generate_parser.sh
+++ b/gfx/angle/src/compiler/translator/generate_parser.sh
@@ -2,27 +2,28 @@
 # Copyright (c) 2010 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.
 
 # Generates GLSL ES parser - glslang_lex.cpp, glslang_tab.h, and glslang_tab.cpp
 
 run_flex()
 {
-input_file=$script_dir/$1.l
-output_source=$script_dir/$1_lex.cpp
+input_file=./$1.l
+output_source=./$1_lex.cpp
 flex --noline --nounistd --outfile=$output_source $input_file
 }
 
 run_bison()
 {
-input_file=$script_dir/$1.y
-output_header=$script_dir/$1_tab.h
-output_source=$script_dir/$1_tab.cpp
+input_file=./$1.y
+output_header=./$1_tab.h
+output_source=./$1_tab.cpp
 bison --no-lines --skeleton=yacc.c --defines=$output_header --output=$output_source $input_file
 }
 
 script_dir=$(dirname $0)
 
 # Generate Parser
+cd $script_dir
 run_flex glslang
 run_bison glslang
 patch --silent --forward < 64bit-lexer-safety.patch
--- a/gfx/angle/src/compiler/translator/glslang.y
+++ b/gfx/angle/src/compiler/translator/glslang.y
@@ -173,20 +173,20 @@ extern void yyerror(YYLTYPE* yylloc, TPa
 %type <interm.intermTypedNode> relational_expression equality_expression
 %type <interm.intermTypedNode> conditional_expression constant_expression
 %type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
 %type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
 %type <interm.intermTypedNode> function_call initializer condition conditionopt
 
 %type <interm.intermNode> translation_unit function_definition
 %type <interm.intermNode> statement simple_statement
-%type <interm.intermAggregate>  statement_list compound_statement
+%type <interm.intermAggregate>  statement_list compound_statement compound_statement_no_new_scope
 %type <interm.intermNode> declaration_statement selection_statement expression_statement
 %type <interm.intermNode> declaration external_declaration
-%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
+%type <interm.intermNode> for_init_statement
 %type <interm.nodePair> selection_rest_statement for_rest_statement
 %type <interm.intermSwitch> switch_statement
 %type <interm.intermCase> case_label
 %type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
 %type <interm> single_declaration init_declarator_list
 
 %type <interm> parameter_declaration parameter_declarator parameter_type_specifier
 %type <interm.qualifier> parameter_qualifier parameter_type_qualifier 
@@ -575,43 +575,18 @@ enter_struct
     : IDENTIFIER LEFT_BRACE {
         if (context->enterStructDeclaration(@1, *$1.string))
             context->recover();
         $$ = $1;
     }
     ;
 
 declaration
-    : function_prototype SEMICOLON   {
-        TFunction &function = *($1.function);
-        
-        TIntermAggregate *prototype = new TIntermAggregate;
-        prototype->setType(function.getReturnType());
-        prototype->setName(function.getMangledName());
-        prototype->setFunctionId(function.getUniqueId());
-        
-        for (size_t i = 0; i < function.getParamCount(); i++)
-        {
-            const TConstParameter &param = function.getParam(i);
-            if (param.name != 0)
-            {
-                TVariable variable(param.name, *param.type);
-                
-                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1);
-            }
-            else
-            {
-                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
-            }
-        }
-        
-        prototype->setOp(EOpPrototype);
-        $$ = prototype;
-
-        context->symbolTable.pop();
+    : function_prototype SEMICOLON {
+        $$ = context->addFunctionPrototypeDeclaration(*($1.function), @1);
     }
     | init_declarator_list SEMICOLON {
         TIntermAggregate *aggNode = $1.intermAggregate;
         if (aggNode && aggNode->getOp() == EOpNull)
             aggNode->setOp(EOpDeclaration);
         $$ = aggNode;
     }
     | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
@@ -1594,30 +1569,17 @@ external_declaration
     }
     ;
 
 function_definition
     : function_prototype {
         context->parseFunctionPrototype(@1, $1.function, &$1.intermAggregate);
     }
     compound_statement_no_new_scope {
-        //?? Check that all paths return a value if return type != void ?
-        //   May be best done as post process phase on intermediate code
-        if (context->getCurrentFunctionType()->getBasicType() != EbtVoid && !context->getFunctionReturnsValue()) {
-            context->error(@1, "function does not return a value:", "", $1.function->getName().c_str());
-            context->recover();
-        }
-        
-        $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$);
-        context->intermediate.setAggregateOperator($$, EOpFunction, @1);
-        $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
-        $$->getAsAggregate()->setType($1.function->getReturnType());
-        $$->getAsAggregate()->setFunctionId($1.function->getUniqueId());
-
-        context->symbolTable.pop();
+        $$ = context->addFunctionDefinition(*($1.function), $1.intermAggregate, $3, @1);
     }
     ;
 
 %%
 
 int glslang_parse(TParseContext* context) {
     return yyparse(context, context->getScanner());
 }
--- a/gfx/angle/src/compiler/translator/glslang_tab.cpp
+++ b/gfx/angle/src/compiler/translator/glslang_tab.cpp
@@ -697,36 +697,36 @@ static const yytype_uint16 yyrline[] =
        0,   212,   212,   213,   216,   226,   229,   234,   239,   244,
      249,   255,   258,   261,   264,   267,   270,   276,   284,   295,
      299,   307,   310,   316,   320,   327,   333,   342,   350,   356,
      363,   373,   376,   379,   382,   392,   393,   394,   395,   403,
      404,   407,   410,   417,   418,   421,   427,   428,   432,   439,
      440,   443,   446,   449,   455,   456,   459,   465,   466,   473,
      474,   481,   482,   489,   490,   496,   497,   503,   504,   510,
      511,   517,   518,   526,   527,   528,   529,   533,   534,   535,
-     539,   543,   547,   551,   558,   561,   567,   575,   583,   611,
-     617,   628,   632,   636,   640,   647,   653,   656,   663,   671,
-     692,   719,   729,   757,   762,   772,   777,   787,   790,   793,
-     796,   802,   809,   812,   816,   820,   825,   830,   837,   841,
-     845,   849,   854,   859,   863,   870,   880,   886,   889,   895,
-     901,   908,   917,   927,   935,   938,   945,   949,   953,   958,
-     966,   969,   973,   977,   986,   995,  1003,  1013,  1025,  1028,
-    1031,  1037,  1044,  1047,  1053,  1056,  1059,  1065,  1068,  1073,
-    1088,  1092,  1096,  1100,  1104,  1108,  1113,  1118,  1123,  1128,
-    1133,  1138,  1143,  1148,  1153,  1158,  1163,  1168,  1173,  1178,
-    1183,  1188,  1193,  1198,  1203,  1208,  1213,  1217,  1221,  1225,
-    1229,  1233,  1237,  1241,  1245,  1249,  1253,  1257,  1261,  1265,
-    1269,  1273,  1281,  1289,  1293,  1306,  1306,  1309,  1309,  1315,
-    1318,  1334,  1337,  1346,  1350,  1356,  1363,  1378,  1382,  1386,
-    1387,  1393,  1394,  1395,  1396,  1397,  1398,  1399,  1403,  1404,
-    1404,  1404,  1414,  1415,  1419,  1419,  1420,  1420,  1425,  1428,
-    1438,  1441,  1447,  1448,  1452,  1460,  1464,  1471,  1471,  1478,
-    1481,  1488,  1493,  1508,  1508,  1513,  1513,  1520,  1520,  1528,
-    1531,  1537,  1540,  1546,  1550,  1557,  1560,  1563,  1566,  1569,
-    1578,  1582,  1589,  1592,  1598,  1598
+     539,   543,   547,   551,   558,   561,   567,   575,   583,   586,
+     592,   603,   607,   611,   615,   622,   628,   631,   638,   646,
+     667,   694,   704,   732,   737,   747,   752,   762,   765,   768,
+     771,   777,   784,   787,   791,   795,   800,   805,   812,   816,
+     820,   824,   829,   834,   838,   845,   855,   861,   864,   870,
+     876,   883,   892,   902,   910,   913,   920,   924,   928,   933,
+     941,   944,   948,   952,   961,   970,   978,   988,  1000,  1003,
+    1006,  1012,  1019,  1022,  1028,  1031,  1034,  1040,  1043,  1048,
+    1063,  1067,  1071,  1075,  1079,  1083,  1088,  1093,  1098,  1103,
+    1108,  1113,  1118,  1123,  1128,  1133,  1138,  1143,  1148,  1153,
+    1158,  1163,  1168,  1173,  1178,  1183,  1188,  1192,  1196,  1200,
+    1204,  1208,  1212,  1216,  1220,  1224,  1228,  1232,  1236,  1240,
+    1244,  1248,  1256,  1264,  1268,  1281,  1281,  1284,  1284,  1290,
+    1293,  1309,  1312,  1321,  1325,  1331,  1338,  1353,  1357,  1361,
+    1362,  1368,  1369,  1370,  1371,  1372,  1373,  1374,  1378,  1379,
+    1379,  1379,  1389,  1390,  1394,  1394,  1395,  1395,  1400,  1403,
+    1413,  1416,  1422,  1423,  1427,  1435,  1439,  1446,  1446,  1453,
+    1456,  1463,  1468,  1483,  1483,  1488,  1488,  1495,  1495,  1503,
+    1506,  1512,  1515,  1521,  1525,  1532,  1535,  1538,  1541,  1544,
+    1553,  1557,  1564,  1567,  1573,  1573
 };
 #endif
 
 #if YYDEBUG || YYERROR_VERBOSE || 0
 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
@@ -3043,42 +3043,17 @@ yyreduce:
         (yyval.lex) = (yyvsp[-1].lex);
     }
 
     break;
 
   case 88:
 
     {
-        TFunction &function = *((yyvsp[-1].interm).function);
-        
-        TIntermAggregate *prototype = new TIntermAggregate;
-        prototype->setType(function.getReturnType());
-        prototype->setName(function.getMangledName());
-        prototype->setFunctionId(function.getUniqueId());
-        
-        for (size_t i = 0; i < function.getParamCount(); i++)
-        {
-            const TConstParameter &param = function.getParam(i);
-            if (param.name != 0)
-            {
-                TVariable variable(param.name, *param.type);
-                
-                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), (yylsp[-1])), (yylsp[-1]));
-            }
-            else
-            {
-                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, (yylsp[-1])), (yylsp[-1]));
-            }
-        }
-        
-        prototype->setOp(EOpPrototype);
-        (yyval.interm.intermNode) = prototype;
-
-        context->symbolTable.pop();
+        (yyval.interm.intermNode) = context->addFunctionPrototypeDeclaration(*((yyvsp[-1].interm).function), (yylsp[-1]));
     }
 
     break;
 
   case 89:
 
     {
         TIntermAggregate *aggNode = (yyvsp[-1].interm).intermAggregate;
@@ -4483,17 +4458,17 @@ yyreduce:
         }
         (yyval.interm.intermAggregate) = (yyvsp[-2].interm.intermAggregate);
     }
 
     break;
 
   case 232:
 
-    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermAggregate); }
 
     break;
 
   case 233:
 
     { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
 
     break;
@@ -4501,17 +4476,17 @@ yyreduce:
   case 234:
 
     { context->symbolTable.push(); }
 
     break;
 
   case 235:
 
-    { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+    { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermAggregate); }
 
     break;
 
   case 236:
 
     { context->symbolTable.push(); }
 
     break;
@@ -4520,29 +4495,29 @@ yyreduce:
 
     { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
 
     break;
 
   case 238:
 
     {
-        (yyval.interm.intermNode) = 0;
+        (yyval.interm.intermAggregate) = 0;
     }
 
     break;
 
   case 239:
 
     {
         if ((yyvsp[-1].interm.intermAggregate)) {
             (yyvsp[-1].interm.intermAggregate)->setOp(EOpSequence);
             (yyvsp[-1].interm.intermAggregate)->setLine((yyloc));
         }
-        (yyval.interm.intermNode) = (yyvsp[-1].interm.intermAggregate);
+        (yyval.interm.intermAggregate) = (yyvsp[-1].interm.intermAggregate);
     }
 
     break;
 
   case 240:
 
     {
         (yyval.interm.intermAggregate) = context->intermediate.makeAggregate((yyvsp[0].interm.intermNode), (yyloc));
@@ -4837,30 +4812,17 @@ yyreduce:
         context->parseFunctionPrototype((yylsp[0]), (yyvsp[0].interm).function, &(yyvsp[0].interm).intermAggregate);
     }
 
     break;
 
   case 275:
 
     {
-        //?? Check that all paths return a value if return type != void ?
-        //   May be best done as post process phase on intermediate code
-        if (context->getCurrentFunctionType()->getBasicType() != EbtVoid && !context->getFunctionReturnsValue()) {
-            context->error((yylsp[-2]), "function does not return a value:", "", (yyvsp[-2].interm).function->getName().c_str());
-            context->recover();
-        }
-        
-        (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[-2].interm).intermAggregate, (yyvsp[0].interm.intermNode), (yyloc));
-        context->intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yylsp[-2]));
-        (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[-2].interm).function->getMangledName().c_str());
-        (yyval.interm.intermNode)->getAsAggregate()->setType((yyvsp[-2].interm).function->getReturnType());
-        (yyval.interm.intermNode)->getAsAggregate()->setFunctionId((yyvsp[-2].interm).function->getUniqueId());
-
-        context->symbolTable.pop();
+        (yyval.interm.intermNode) = context->addFunctionDefinition(*((yyvsp[-2].interm).function), (yyvsp[-2].interm).intermAggregate, (yyvsp[0].interm.intermAggregate), (yylsp[-2]));
     }
 
     break;
 
 
 
       default: break;
     }
--- a/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp
+++ b/gfx/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp
@@ -49,33 +49,27 @@ void RestrictFragmentShaderTiming::enfor
     mNumErrors = 0;
 
     // FIXME(mvujovic): The dependency graph does not support user defined function calls right now,
     // so we generate errors for them.
     validateUserDefinedFunctionCallUsage(graph);
 
     // Starting from each sampler, traverse the dependency graph and generate an error each time we
     // hit a node where sampler dependent values are not allowed.
-    for (TGraphSymbolVector::const_iterator iter = graph.beginSamplerSymbols();
-         iter != graph.endSamplerSymbols();
-         ++iter)
+    for (auto samplerSymbol : graph.samplerSymbols())
     {
-        TGraphSymbol* samplerSymbol = *iter;
         clearVisited();
         samplerSymbol->traverse(this);
     }
 }
 
 void RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph)
 {
-    for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
-         iter != graph.endUserDefinedFunctionCalls();
-         ++iter)
+    for (const auto* functionCall : graph.userDefinedFunctionCalls())
     {
-        TGraphFunctionCall* functionCall = *iter;
         beginError(functionCall->getIntermFunctionCall());
         mSink << "A call to a user defined function is not permitted.\n";
     }
 }
 
 void RestrictFragmentShaderTiming::beginError(const TIntermNode* node)
 {
     ++mNumErrors;
--- a/gfx/angle/src/libANGLE/Buffer.cpp
+++ b/gfx/angle/src/libANGLE/Buffer.cpp
@@ -13,32 +13,43 @@
 #include "libANGLE/renderer/Renderer.h"
 
 namespace gl
 {
 
 Buffer::Buffer(rx::BufferImpl *impl, GLuint id)
     : RefCountObject(id),
       mBuffer(impl),
+      mLabel(),
       mUsage(GL_STATIC_DRAW),
       mSize(0),
       mAccessFlags(0),
       mAccess(GL_WRITE_ONLY_OES),
       mMapped(GL_FALSE),
       mMapPointer(NULL),
       mMapOffset(0),
       mMapLength(0)
 {
 }
 
 Buffer::~Buffer()
 {
     SafeDelete(mBuffer);
 }
 
+void Buffer::setLabel(const std::string &label)
+{
+    mLabel = label;
+}
+
+const std::string &Buffer::getLabel() const
+{
+    return mLabel;
+}
+
 Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
 {
     gl::Error error = mBuffer->setData(data, size, usage);
     if (error.isError())
     {
         return error;
     }
 
--- a/gfx/angle/src/libANGLE/Buffer.h
+++ b/gfx/angle/src/libANGLE/Buffer.h
@@ -7,34 +7,37 @@
 // Buffer.h: Defines the gl::Buffer class, representing storage of vertex and/or
 // index data. Implements GL buffer objects and related functionality.
 // [OpenGL ES 2.0.24] section 2.9 page 21.
 
 #ifndef LIBANGLE_BUFFER_H_
 #define LIBANGLE_BUFFER_H_
 
 #include "common/angleutils.h"
+#include "libANGLE/Debug.h"
 #include "libANGLE/Error.h"
 #include "libANGLE/IndexRangeCache.h"
 #include "libANGLE/RefCountObject.h"
 
 namespace rx
 {
 class BufferImpl;
 };
 
 namespace gl
 {
 
-class Buffer : public RefCountObject
+class Buffer final : public RefCountObject, public LabeledObject
 {
   public:
     Buffer(rx::BufferImpl *impl, GLuint id);
+    virtual ~Buffer();
 
-    virtual ~Buffer();
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
 
     Error bufferData(const void *data, GLsizeiptr size, GLenum usage);
     Error bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
     Error copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
     Error map(GLenum access);
     Error mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access);
     Error unmap(GLboolean *result);
 
@@ -56,16 +59,18 @@ class Buffer : public RefCountObject
     GLint64 getMapLength() const { return mMapLength; }
     GLint64 getSize() const { return mSize; }
 
     rx::BufferImpl *getImplementation() const { return mBuffer; }
 
   private:
     rx::BufferImpl *mBuffer;
 
+    std::string mLabel;
+
     GLenum mUsage;
     GLint64 mSize;
     GLbitfield mAccessFlags;
     GLenum mAccess;
     GLboolean mMapped;
     GLvoid *mMapPointer;
     GLint64 mMapOffset;
     GLint64 mMapLength;
--- a/gfx/angle/src/libANGLE/Caps.cpp
+++ b/gfx/angle/src/libANGLE/Caps.cpp
@@ -97,16 +97,17 @@ Extensions::Extensions()
       packedDepthStencil(false),
       getProgramBinary(false),
       rgb8rgba8(false),
       textureFormatBGRA8888(false),
       readFormatBGRA(false),
       pixelBufferObject(false),
       mapBuffer(false),
       mapBufferRange(false),
+      colorBufferHalfFloat(false),
       textureHalfFloat(false),
       textureHalfFloatLinear(false),
       textureFloat(false),
       textureFloatLinear(false),
       textureRG(false),
       textureCompressionDXT1(false),
       textureCompressionDXT3(false),
       textureCompressionDXT5(false),
@@ -118,16 +119,19 @@ Extensions::Extensions()
       textureStorage(false),
       textureNPOT(false),
       drawBuffers(false),
       textureFilterAnisotropic(false),
       maxTextureAnisotropy(false),
       occlusionQueryBoolean(false),
       fence(false),
       timerQuery(false),
+      disjointTimerQuery(false),
+      queryCounterBitsTimeElapsed(0),
+      queryCounterBitsTimestamp(0),
       robustness(false),
       blendMinMax(false),
       framebufferBlit(false),
       framebufferMultisample(false),
       instancedArrays(false),
       packReverseRowOrder(false),
       standardDerivatives(false),
       shaderTextureLOD(false),
@@ -141,16 +145,23 @@ Extensions::Extensions()
       discardFramebuffer(false),
       debugMarker(false),
       eglImage(false),
       eglImageExternal(false),
       eglImageExternalEssl3(false),
       unpackSubimage(false),
       packSubimage(false),
       vertexArrayObject(false),
+      debug(false),
+      maxDebugMessageLength(0),
+      maxDebugLoggedMessages(0),
+      maxDebugGroupStackDepth(0),
+      maxLabelLength(0),
+      noError(false),
+      lossyETCDecode(false),
       colorBufferFloat(false)
 {
 }
 
 std::vector<std::string> Extensions::getStrings() const
 {
     std::vector<std::string> extensionStrings;
 
@@ -160,16 +171,17 @@ std::vector<std::string> Extensions::get
     InsertExtensionString("GL_OES_packed_depth_stencil",         packedDepthStencil,        &extensionStrings);
     InsertExtensionString("GL_OES_get_program_binary",           getProgramBinary,          &extensionStrings);
     InsertExtensionString("GL_OES_rgb8_rgba8",                   rgb8rgba8,                 &extensionStrings);
     InsertExtensionString("GL_EXT_texture_format_BGRA8888",      textureFormatBGRA8888,     &extensionStrings);
     InsertExtensionString("GL_EXT_read_format_bgra",             readFormatBGRA,            &extensionStrings);
     InsertExtensionString("GL_NV_pixel_buffer_object",           pixelBufferObject,         &extensionStrings);
     InsertExtensionString("GL_OES_mapbuffer",                    mapBuffer,                 &extensionStrings);
     InsertExtensionString("GL_EXT_map_buffer_range",             mapBufferRange,            &extensionStrings);
+    InsertExtensionString("GL_EXT_color_buffer_half_float",      colorBufferHalfFloat,      &extensionStrings);
     InsertExtensionString("GL_OES_texture_half_float",           textureHalfFloat,          &extensionStrings);
     InsertExtensionString("GL_OES_texture_half_float_linear",    textureHalfFloatLinear,    &extensionStrings);
     InsertExtensionString("GL_OES_texture_float",                textureFloat,              &extensionStrings);
     InsertExtensionString("GL_OES_texture_float_linear",         textureFloatLinear,        &extensionStrings);
     InsertExtensionString("GL_EXT_texture_rg",                   textureRG,                 &extensionStrings);
     InsertExtensionString("GL_EXT_texture_compression_dxt1",     textureCompressionDXT1,    &extensionStrings);
     InsertExtensionString("GL_ANGLE_texture_compression_dxt3",   textureCompressionDXT3,    &extensionStrings);
     InsertExtensionString("GL_ANGLE_texture_compression_dxt5",   textureCompressionDXT5,    &extensionStrings);
@@ -181,16 +193,17 @@ std::vector<std::string> Extensions::get
     InsertExtensionString("GL_OES_depth32",                      depth32,                   &extensionStrings);
     InsertExtensionString("GL_EXT_texture_storage",              textureStorage,            &extensionStrings);
     InsertExtensionString("GL_OES_texture_npot",                 textureNPOT,               &extensionStrings);
     InsertExtensionString("GL_EXT_draw_buffers",                 drawBuffers,               &extensionStrings);
     InsertExtensionString("GL_EXT_texture_filter_anisotropic",   textureFilterAnisotropic,  &extensionStrings);
     InsertExtensionString("GL_EXT_occlusion_query_boolean",      occlusionQueryBoolean,     &extensionStrings);
     InsertExtensionString("GL_NV_fence",                         fence,                     &extensionStrings);
     InsertExtensionString("GL_ANGLE_timer_query",                timerQuery,                &extensionStrings);
+    InsertExtensionString("GL_EXT_disjoint_timer_query",         disjointTimerQuery,        &extensionStrings);
     InsertExtensionString("GL_EXT_robustness",                   robustness,                &extensionStrings);
     InsertExtensionString("GL_EXT_blend_minmax",                 blendMinMax,               &extensionStrings);
     InsertExtensionString("GL_ANGLE_framebuffer_blit",           framebufferBlit,           &extensionStrings);
     InsertExtensionString("GL_ANGLE_framebuffer_multisample",    framebufferMultisample,    &extensionStrings);
     InsertExtensionString("GL_ANGLE_instanced_arrays",           instancedArrays,           &extensionStrings);
     InsertExtensionString("GL_ANGLE_pack_reverse_row_order",     packReverseRowOrder,       &extensionStrings);
     InsertExtensionString("GL_OES_standard_derivatives",         standardDerivatives,       &extensionStrings);
     InsertExtensionString("GL_EXT_shader_texture_lod",           shaderTextureLOD,          &extensionStrings);
@@ -205,16 +218,21 @@ std::vector<std::string> Extensions::get
     InsertExtensionString("GL_EXT_debug_marker",                 debugMarker,               &extensionStrings);
     InsertExtensionString("GL_OES_EGL_image",                    eglImage,                  &extensionStrings);
     InsertExtensionString("GL_OES_EGL_image_external",           eglImageExternal,          &extensionStrings);
     InsertExtensionString("GL_OES_EGL_image_external_essl3",     eglImageExternalEssl3,     &extensionStrings);
     InsertExtensionString("GL_EXT_unpack_subimage",              unpackSubimage,            &extensionStrings);
     InsertExtensionString("GL_NV_pack_subimage",                 packSubimage,              &extensionStrings);
     InsertExtensionString("GL_EXT_color_buffer_float",           colorBufferFloat,          &extensionStrings);
     InsertExtensionString("GL_OES_vertex_array_object",          vertexArrayObject,         &extensionStrings);
+    InsertExtensionString("GL_KHR_debug",                        debug,                     &extensionStrings);
+    // TODO(jmadill): Enable this when complete.
+    //InsertExtensionString("GL_KHR_no_error",                     noError,                   &extensionStrings);
+
+    InsertExtensionString("GL_ANGLE_lossy_etc_decode",           lossyETCDecode,            &extensionStrings);
     // clang-format on
 
     return extensionStrings;
 }
 
 Limitations::Limitations()
     : noFrontFacingSupport(false),
       noSampleAlphaToCoverageSupport(false),
@@ -274,16 +292,28 @@ static bool DetermineRGB8AndRGBA8Texture
 static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_BGRA8_EXT);
 
     return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
 }
 
+// Checks for GL_OES_color_buffer_half_float support
+static bool DetermineColorBufferHalfFloatSupport(const TextureCapsMap &textureCaps)
+{
+    std::vector<GLenum> requiredFormats;
+    requiredFormats.push_back(GL_RGBA16F);
+    requiredFormats.push_back(GL_RGB16F);
+    requiredFormats.push_back(GL_RG16F);
+    requiredFormats.push_back(GL_R16F);
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+}
+
 // Checks for GL_OES_texture_half_float support
 static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_RGB16F);
     requiredFormats.push_back(GL_RGBA16F);
 
     return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
@@ -291,17 +321,18 @@ static bool DetermineHalfFloatTextureSup
 
 // Checks for GL_OES_texture_half_float_linear support
 static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_RGB16F);
     requiredFormats.push_back(GL_RGBA16F);
 
-    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+    return DetermineHalfFloatTextureSupport(textureCaps) &&
+           GetFormatSupport(textureCaps, requiredFormats, true, true, false);
 }
 
 // Checks for GL_OES_texture_float support
 static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_RGB32F);
     requiredFormats.push_back(GL_RGBA32F);
@@ -311,17 +342,18 @@ static bool DetermineFloatTextureSupport
 
 // Checks for GL_OES_texture_float_linear support
 static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_RGB32F);
     requiredFormats.push_back(GL_RGBA32F);
 
-    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+    return DetermineFloatTextureSupport(textureCaps) &&
+           GetFormatSupport(textureCaps, requiredFormats, true, true, false);
 }
 
 // Checks for GL_EXT_texture_rg support
 static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps, bool checkHalfFloatFormats, bool checkFloatFormats)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_R8);
     requiredFormats.push_back(GL_RG8);
@@ -461,16 +493,17 @@ static bool DetermineColorBufferFloatSup
     return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
 }
 
 void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
 {
     packedDepthStencil = DeterminePackedDepthStencilSupport(textureCaps);
     rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps);
     textureFormatBGRA8888 = DetermineBGRA8TextureSupport(textureCaps);
+    colorBufferHalfFloat      = DetermineColorBufferHalfFloatSupport(textureCaps);
     textureHalfFloat = DetermineHalfFloatTextureSupport(textureCaps);
     textureHalfFloatLinear = DetermineHalfFloatTextureFilteringSupport(textureCaps);
     textureFloat = DetermineFloatTextureSupport(textureCaps);
     textureFloatLinear = DetermineFloatTextureFilteringSupport(textureCaps);
     textureRG = DetermineRGTextureSupport(textureCaps, textureHalfFloat, textureFloat);
     textureCompressionDXT1 = DetermineDXT1TextureSupport(textureCaps);
     textureCompressionDXT3 = DetermineDXT3TextureSupport(textureCaps);
     textureCompressionDXT5 = DetermineDXT5TextureSupport(textureCaps);
@@ -583,53 +616,62 @@ Caps::Caps()
 
 DisplayExtensions::DisplayExtensions()
     : createContextRobustness(false),
       d3dShareHandleClientBuffer(false),
       surfaceD3DTexture2DShareHandle(false),
       querySurfacePointer(false),
       windowFixedSize(false),
       keyedMutex(false),
+      surfaceOrientation(false),
       postSubBuffer(false),
       createContext(false),
       deviceQuery(false),
       image(false),
       imageBase(false),
       imagePixmap(false),
       glTexture2DImage(false),
       glTextureCubemapImage(false),
       glTexture3DImage(false),
       glRenderbufferImage(false),
-      getAllProcAddresses(false)
+      getAllProcAddresses(false),
+      flexibleSurfaceCompatibility(false),
+      directComposition(false),
+      createContextNoError(false)
 {
 }
 
 std::vector<std::string> DisplayExtensions::getStrings() const
 {
     std::vector<std::string> extensionStrings;
 
     // clang-format off
     //                   | Extension name                                 | Supported flag                | Output vector   |
     InsertExtensionString("EGL_EXT_create_context_robustness",             createContextRobustness,        &extensionStrings);
     InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer",      d3dShareHandleClientBuffer,     &extensionStrings);
     InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings);
     InsertExtensionString("EGL_ANGLE_query_surface_pointer",               querySurfacePointer,            &extensionStrings);
     InsertExtensionString("EGL_ANGLE_window_fixed_size",                   windowFixedSize,                &extensionStrings);
     InsertExtensionString("EGL_ANGLE_keyed_mutex",                         keyedMutex,                     &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_surface_orientation",                 surfaceOrientation,             &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_direct_composition",                  directComposition,              &extensionStrings);
     InsertExtensionString("EGL_NV_post_sub_buffer",                        postSubBuffer,                  &extensionStrings);
     InsertExtensionString("EGL_KHR_create_context",                        createContext,                  &extensionStrings);
     InsertExtensionString("EGL_EXT_device_query",                          deviceQuery,                    &extensionStrings);
     InsertExtensionString("EGL_KHR_image",                                 image,                          &extensionStrings);
     InsertExtensionString("EGL_KHR_image_base",                            imageBase,                      &extensionStrings);
     InsertExtensionString("EGL_KHR_image_pixmap",                          imagePixmap,                    &extensionStrings);
     InsertExtensionString("EGL_KHR_gl_texture_2D_image",                   glTexture2DImage,               &extensionStrings);
     InsertExtensionString("EGL_KHR_gl_texture_cubemap_image",              glTextureCubemapImage,          &extensionStrings);
     InsertExtensionString("EGL_KHR_gl_texture_3D_image",                   glTexture3DImage,               &extensionStrings);
     InsertExtensionString("EGL_KHR_gl_renderbuffer_image",                 glRenderbufferImage,            &extensionStrings);
     InsertExtensionString("EGL_KHR_get_all_proc_addresses",                getAllProcAddresses,            &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility",      flexibleSurfaceCompatibility,   &extensionStrings);
+    // TODO(jmadill): Enable this when complete.
+    //InsertExtensionString("KHR_create_context_no_error",                   createContextNoError,           &extensionStrings);
     // clang-format on
 
     return extensionStrings;
 }
 
 DeviceExtensions::DeviceExtensions()
     : deviceD3D(false)
 {
@@ -650,16 +692,17 @@ ClientExtensions::ClientExtensions()
       platformBase(false),
       platformDevice(false),
       platformANGLE(false),
       platformANGLED3D(false),
       platformANGLEOpenGL(false),
       deviceCreation(false),
       deviceCreationD3D11(false),
       x11Visual(false),
+      experimentalPresentPath(false),
       clientGetAllProcAddresses(false)
 {
 }
 
 std::vector<std::string> ClientExtensions::getStrings() const
 {
     std::vector<std::string> extensionStrings;
 
@@ -669,15 +712,16 @@ std::vector<std::string> ClientExtension
     InsertExtensionString("EGL_EXT_platform_base",                 platformBase,              &extensionStrings);
     InsertExtensionString("EGL_EXT_platform_device",               platformDevice,            &extensionStrings);
     InsertExtensionString("EGL_ANGLE_platform_angle",              platformANGLE,             &extensionStrings);
     InsertExtensionString("EGL_ANGLE_platform_angle_d3d",          platformANGLED3D,          &extensionStrings);
     InsertExtensionString("EGL_ANGLE_platform_angle_opengl",       platformANGLEOpenGL,       &extensionStrings);
     InsertExtensionString("EGL_ANGLE_device_creation",             deviceCreation,            &extensionStrings);
     InsertExtensionString("EGL_ANGLE_device_creation_d3d11",       deviceCreationD3D11,       &extensionStrings);
     InsertExtensionString("EGL_ANGLE_x11_visual",                  x11Visual,                 &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_experimental_present_path",   experimentalPresentPath,   &extensionStrings);
     InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings);
     // clang-format on
 
     return extensionStrings;
 }
 
 }
--- a/gfx/angle/src/libANGLE/Caps.h
+++ b/gfx/angle/src/libANGLE/Caps.h
@@ -71,20 +71,22 @@ struct Extensions
     // Generate a vector of supported extension strings
     std::vector<std::string> getStrings() const;
 
     // Set all texture related extension support based on the supported textures.
     // Determines support for:
     // GL_OES_packed_depth_stencil
     // GL_OES_rgb8_rgba8
     // GL_EXT_texture_format_BGRA8888
+    // GL_EXT_color_buffer_half_float,
     // GL_OES_texture_half_float, GL_OES_texture_half_float_linear
     // GL_OES_texture_float, GL_OES_texture_float_linear
     // GL_EXT_texture_rg
-    // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3, GL_ANGLE_texture_compression_dxt5
+    // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3,
+    // GL_ANGLE_texture_compression_dxt5
     // GL_KHR_texture_compression_astc_hdr, GL_KHR_texture_compression_astc_ldr
     // GL_OES_compressed_ETC1_RGB8_texture
     // GL_EXT_sRGB
     // GL_ANGLE_depth_texture, GL_OES_depth32
     // GL_EXT_color_buffer_float
     void setTextureExtensionSupport(const TextureCapsMap &textureCaps);
 
     // ES2 Extension support
@@ -111,16 +113,21 @@ struct Extensions
 
     // GL_NV_pixel_buffer_object
     bool pixelBufferObject;
 
     // GL_OES_mapbuffer and GL_EXT_map_buffer_range
     bool mapBuffer;
     bool mapBufferRange;
 
+    // GL_EXT_color_buffer_half_float
+    // Together with GL_OES_texture_half_float in a GLES 2.0 context, implies that half-float
+    // textures are renderable.
+    bool colorBufferHalfFloat;
+
     // GL_OES_texture_half_float and GL_OES_texture_half_float_linear
     // Implies that TextureCaps for GL_RGB16F, GL_RGBA16F, GL_ALPHA32F_EXT, GL_LUMINANCE32F_EXT and
     // GL_LUMINANCE_ALPHA32F_EXT exist
     bool textureHalfFloat;
     bool textureHalfFloatLinear;
 
     // GL_OES_texture_float and GL_OES_texture_float_linear
     // Implies that TextureCaps for GL_RGB32F, GL_RGBA32F, GL_ALPHA16F_EXT, GL_LUMINANCE16F_EXT and
@@ -179,16 +186,21 @@ struct Extensions
     bool occlusionQueryBoolean;
 
     // GL_NV_fence
     bool fence;
 
     // GL_ANGLE_timer_query
     bool timerQuery;
 
+    // GL_EXT_disjoint_timer_query
+    bool disjointTimerQuery;
+    GLuint queryCounterBitsTimeElapsed;
+    GLuint queryCounterBitsTimestamp;
+
     // GL_EXT_robustness
     bool robustness;
 
     // GL_EXT_blend_minmax
     bool blendMinMax;
 
     // GL_ANGLE_framebuffer_blit
     bool framebufferBlit;
@@ -248,16 +260,29 @@ struct Extensions
     bool unpackSubimage;
 
     // NV_pack_subimage
     bool packSubimage;
 
     // GL_OES_vertex_array_object
     bool vertexArrayObject;
 
+    // GL_KHR_debug
+    bool debug;
+    GLuint maxDebugMessageLength;
+    GLuint maxDebugLoggedMessages;
+    GLuint maxDebugGroupStackDepth;
+    GLuint maxLabelLength;
+
+    // KHR_no_error
+    bool noError;
+
+    // GL_ANGLE_lossy_etc_decode
+    bool lossyETCDecode;
+
     // ES3 Extension support
 
     // GL_EXT_color_buffer_float
     bool colorBufferFloat;
 };
 
 struct Limitations
 {
@@ -408,16 +433,19 @@ struct DisplayExtensions
     bool querySurfacePointer;
 
     // EGL_ANGLE_window_fixed_size
     bool windowFixedSize;
 
     // EGL_ANGLE_keyed_mutex
     bool keyedMutex;
 
+    // EGL_ANGLE_surface_orientation
+    bool surfaceOrientation;
+
     // EGL_NV_post_sub_buffer
     bool postSubBuffer;
 
     // EGL_KHR_create_context
     bool createContext;
 
     // EGL_EXT_device_query
     bool deviceQuery;
@@ -440,16 +468,25 @@ struct DisplayExtensions
     // EGL_KHR_gl_texture_3D_image
     bool glTexture3DImage;
 
     // EGL_KHR_gl_renderbuffer_image
     bool glRenderbufferImage;
 
     // EGL_KHR_get_all_proc_addresses
     bool getAllProcAddresses;
+
+    // EGL_ANGLE_flexible_surface_compatibility
+    bool flexibleSurfaceCompatibility;
+
+    // EGL_ANGLE_direct_composition
+    bool directComposition;
+
+    // KHR_create_context_no_error
+    bool createContextNoError;
 };
 
 struct DeviceExtensions
 {
     DeviceExtensions();
 
     // Generate a vector of supported extension strings
     std::vector<std::string> getStrings() const;
@@ -487,15 +524,18 @@ struct ClientExtensions
     bool deviceCreation;
 
     // EGL_ANGLE_device_creation_d3d11
     bool deviceCreationD3D11;
 
     // EGL_ANGLE_x11_visual
     bool x11Visual;
 
+    // EGL_ANGLE_experimental_present_path
+    bool experimentalPresentPath;
+
     // EGL_KHR_client_get_all_proc_addresses
     bool clientGetAllProcAddresses;
 };
 
 }
 
 #endif // LIBANGLE_CAPS_H_
--- a/gfx/angle/src/libANGLE/Config.cpp
+++ b/gfx/angle/src/libANGLE/Config.cpp
@@ -52,17 +52,18 @@ Config::Config()
       renderableType(0),
       sampleBuffers(0),
       samples(0),
       stencilSize(0),
       surfaceType(0),
       transparentType(EGL_NONE),
       transparentRedValue(0),
       transparentGreenValue(0),
-      transparentBlueValue(0)
+      transparentBlueValue(0),
+      optimalOrientation(0)
 {
 }
 
 EGLint ConfigSet::add(const Config &config)
 {
     // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4)
     EGLint id = static_cast<EGLint>(mConfigs.size()) + 1;
 
@@ -246,16 +247,19 @@ std::vector<const Config*> ConfigSet::fi
               case EGL_ALPHA_MASK_SIZE:           match = config.alphaMaskSize >= attributeValue;                     break;
               case EGL_COLOR_BUFFER_TYPE:         match = config.colorBufferType == (EGLenum)attributeValue;          break;
               case EGL_RENDERABLE_TYPE:           match = (config.renderableType & attributeValue) == attributeValue; break;
               case EGL_MATCH_NATIVE_PIXMAP:       match = false; UNIMPLEMENTED();                                     break;
               case EGL_CONFORMANT:                match = (config.conformant & attributeValue) == attributeValue;     break;
               case EGL_MAX_PBUFFER_WIDTH:         match = config.maxPBufferWidth >= attributeValue;                   break;
               case EGL_MAX_PBUFFER_HEIGHT:        match = config.maxPBufferHeight >= attributeValue;                  break;
               case EGL_MAX_PBUFFER_PIXELS:        match = config.maxPBufferPixels >= attributeValue;                  break;
+              case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+                  match = config.optimalOrientation == attributeValue;
+                  break;
               default: UNREACHABLE();
             }
 
             if (!match)
             {
                 break;
             }
         }
--- a/gfx/angle/src/libANGLE/Config.h
+++ b/gfx/angle/src/libANGLE/Config.h
@@ -59,16 +59,17 @@ struct Config
     EGLint sampleBuffers;           // Number of multisample buffers
     EGLint samples;                 // Number of samples per pixel
     EGLint stencilSize;             // Bits of Stencil in the stencil buffer
     EGLint surfaceType;             // Which types of EGL surfaces are supported.
     EGLenum transparentType;        // Type of transparency supported
     EGLint transparentRedValue;     // Transparent red value
     EGLint transparentGreenValue;   // Transparent green value
     EGLint transparentBlueValue;    // Transparent blue value
+    EGLint optimalOrientation;      // Optimal window surface orientation
 };
 
 class ConfigSet
 {
   public:
     EGLint add(const Config &config);
     const Config &get(EGLint id) const;
 
--- a/gfx/angle/src/libANGLE/Context.cpp
+++ b/gfx/angle/src/libANGLE/Context.cpp
@@ -31,62 +31,131 @@
 #include "libANGLE/VertexArray.h"
 #include "libANGLE/formatutils.h"
 #include "libANGLE/validationES.h"
 #include "libANGLE/renderer/Renderer.h"
 
 namespace
 {
 
+template <typename T>
+gl::Error GetQueryObjectParameter(gl::Context *context, GLuint id, GLenum pname, T *params)
+{
+    gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
+    ASSERT(queryObject != nullptr);
+
+    switch (pname)
+    {
+        case GL_QUERY_RESULT_EXT:
+            return queryObject->getResult(params);
+        case GL_QUERY_RESULT_AVAILABLE_EXT:
+        {
+            bool available;
+            gl::Error error = queryObject->isResultAvailable(&available);
+            if (!error.isError())
+            {
+                *params = static_cast<T>(available ? GL_TRUE : GL_FALSE);
+            }
+            return error;
+        }
+        default:
+            UNREACHABLE();
+            return gl::Error(GL_INVALID_OPERATION, "Unreachable Error");
+    }
+}
+
 void MarkTransformFeedbackBufferUsage(gl::TransformFeedback *transformFeedback)
 {
     if (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
     {
         for (size_t tfBufferIndex = 0; tfBufferIndex < transformFeedback->getIndexedBufferCount();
              tfBufferIndex++)
         {
             const OffsetBindingPointer<gl::Buffer> &buffer =
                 transformFeedback->getIndexedBuffer(tfBufferIndex);
             if (buffer.get() != nullptr)
             {
                 buffer->onTransformFeedback();
             }
         }
     }
 }
+
+// Attribute map queries.
+EGLint GetClientVersion(const egl::AttributeMap &attribs)
+{
+    return attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1);
+}
+
+GLenum GetResetStrategy(const egl::AttributeMap &attribs)
+{
+    EGLenum attrib = attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
+                                 EGL_NO_RESET_NOTIFICATION_EXT);
+    switch (attrib)
+    {
+        case EGL_NO_RESET_NOTIFICATION:
+            return GL_NO_RESET_NOTIFICATION_EXT;
+        case EGL_LOSE_CONTEXT_ON_RESET:
+            return GL_LOSE_CONTEXT_ON_RESET_EXT;
+        default:
+            UNREACHABLE();
+            return GL_NONE;
+    }
+}
+
+bool GetRobustAccess(const egl::AttributeMap &attribs)
+{
+    return (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE);
+}
+
+bool GetDebug(const egl::AttributeMap &attribs)
+{
+    return (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE);
+}
+
+bool GetNoError(const egl::AttributeMap &attribs)
+{
+    return (attribs.get(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, EGL_FALSE) == EGL_TRUE);
+}
+
 }  // anonymous namespace
 
 namespace gl
 {
 
 Context::Context(const egl::Config *config,
-                 int clientVersion,
                  const Context *shareContext,
                  rx::Renderer *renderer,
-                 bool notifyResets,
-                 bool robustAccess)
-    : ValidationContext(clientVersion,
+                 const egl::AttributeMap &attribs)
+    : ValidationContext(GetClientVersion(attribs),
                         mState,
                         mCaps,
                         mTextureCaps,
                         mExtensions,
                         nullptr,
-                        mLimitations),
+                        mLimitations,
+                        GetNoError(attribs)),
+      mCompiler(nullptr),
       mRenderer(renderer),
+      mClientVersion(GetClientVersion(attribs)),
       mConfig(config),
-      mCurrentSurface(nullptr)
+      mClientType(EGL_OPENGL_ES_API),
+      mHasBeenCurrent(false),
+      mContextLost(false),
+      mResetStatus(GL_NO_ERROR),
+      mResetStrategy(GetResetStrategy(attribs)),
+      mRobustAccess(GetRobustAccess(attribs)),
+      mCurrentSurface(nullptr),
+      mResourceManager(nullptr)
 {
-    ASSERT(robustAccess == false);   // Unimplemented
+    ASSERT(!mRobustAccess);  // Unimplemented
 
-    initCaps(clientVersion);
-    mState.initialize(mCaps, clientVersion);
+    initCaps(mClientVersion);
 
-    mClientVersion = clientVersion;
-
-    mClientType = EGL_OPENGL_ES_API;
+    mState.initialize(mCaps, mExtensions, mClientVersion, GetDebug(attribs));
 
     mFenceNVHandleAllocator.setBaseHandle(0);
 
     if (shareContext != NULL)
     {
         mResourceManager = shareContext->mResourceManager;
         mResourceManager->addRef();
     }
@@ -142,22 +211,16 @@ Context::Context(const egl::Config *conf
     {
         // [OpenGL ES 3.0.2] section 2.14.1 pg 85:
         // In the initial state, a default transform feedback object is bound and treated as
         // a transform feedback object with a name of zero. That object is bound any time
         // BindTransformFeedback is called with id of zero
         bindTransformFeedback(0);
     }
 
-    mHasBeenCurrent = false;
-    mContextLost = false;
-    mResetStatus = GL_NO_ERROR;
-    mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
-    mRobustAccess = robustAccess;
-
     mCompiler = new Compiler(mRenderer, getData());
 }
 
 Context::~Context()
 {
     mState.reset();
 
     for (auto framebuffer : mFramebufferMap)
@@ -248,16 +311,19 @@ void Context::makeCurrent(egl::Surface *
             mState.setReadFramebufferBinding(newDefault);
         }
         if (mState.getDrawFramebuffer() == nullptr)
         {
             mState.setDrawFramebufferBinding(newDefault);
         }
         mFramebufferMap[0] = newDefault;
     }
+
+    // Notify the renderer of a context switch
+    mRenderer->onMakeCurrent(getData());
 }
 
 void Context::releaseSurface()
 {
     ASSERT(mCurrentSurface != nullptr);
 
     // Remove the default framebuffer
     {
@@ -498,17 +564,17 @@ void Context::deleteQuery(GLuint query)
         if (queryObject->second)
         {
             queryObject->second->release();
         }
         mQueryMap.erase(queryObject);
     }
 }
 
-Buffer *Context::getBuffer(GLuint handle)
+Buffer *Context::getBuffer(GLuint handle) const
 {
     return mResourceManager->getBuffer(handle);
 }
 
 Shader *Context::getShader(GLuint handle) const
 {
     return mResourceManager->getShader(handle);
 }
@@ -518,17 +584,17 @@ Program *Context::getProgram(GLuint hand
     return mResourceManager->getProgram(handle);
 }
 
 Texture *Context::getTexture(GLuint handle) const
 {
     return mResourceManager->getTexture(handle);
 }
 
-Renderbuffer *Context::getRenderbuffer(GLuint handle)
+Renderbuffer *Context::getRenderbuffer(GLuint handle) const
 {
     return mResourceManager->getRenderbuffer(handle);
 }
 
 FenceSync *Context::getFenceSync(GLsync handle) const
 {
     return mResourceManager->getFenceSync(static_cast<GLuint>(reinterpret_cast<uintptr_t>(handle)));
 }
@@ -545,16 +611,51 @@ Sampler *Context::getSampler(GLuint hand
 }
 
 TransformFeedback *Context::getTransformFeedback(GLuint handle) const
 {
     auto iter = mTransformFeedbackMap.find(handle);
     return (iter != mTransformFeedbackMap.end()) ? iter->second : nullptr;
 }
 
+LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const
+{
+    switch (identifier)
+    {
+        case GL_BUFFER:
+            return getBuffer(name);
+        case GL_SHADER:
+            return getShader(name);
+        case GL_PROGRAM:
+            return getProgram(name);
+        case GL_VERTEX_ARRAY:
+            return getVertexArray(name);
+        case GL_QUERY:
+            return getQuery(name);
+        case GL_TRANSFORM_FEEDBACK:
+            return getTransformFeedback(name);
+        case GL_SAMPLER:
+            return getSampler(name);
+        case GL_TEXTURE:
+            return getTexture(name);
+        case GL_RENDERBUFFER:
+            return getRenderbuffer(name);
+        case GL_FRAMEBUFFER:
+            return getFramebuffer(name);
+        default:
+            UNREACHABLE();
+            return nullptr;
+    }
+}
+
+LabeledObject *Context::getLabeledObjectFromPtr(const void *ptr) const
+{
+    return getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr)));
+}
+
 bool Context::isSampler(GLuint samplerName) const
 {
     return mResourceManager->isSampler(samplerName);
 }
 
 void Context::bindArrayBuffer(unsigned int buffer)
 {
     mResourceManager->checkBufferAllocation(buffer);
@@ -583,34 +684,26 @@ void Context::bindTexture(GLenum target,
         texture = getTexture(handle);
     }
 
     ASSERT(texture);
 
     mState.setSamplerTexture(target, texture);
 }
 
-void Context::bindReadFramebuffer(GLuint framebuffer)
+void Context::bindReadFramebuffer(GLuint framebufferHandle)
 {
-    if (!getFramebuffer(framebuffer))
-    {
-        mFramebufferMap[framebuffer] = new Framebuffer(mCaps, mRenderer, framebuffer);
-    }
-
-    mState.setReadFramebufferBinding(getFramebuffer(framebuffer));
+    Framebuffer *framebuffer = checkFramebufferAllocation(framebufferHandle);
+    mState.setReadFramebufferBinding(framebuffer);
 }
 
-void Context::bindDrawFramebuffer(GLuint framebuffer)
+void Context::bindDrawFramebuffer(GLuint framebufferHandle)
 {
-    if (!getFramebuffer(framebuffer))
-    {
-        mFramebufferMap[framebuffer] = new Framebuffer(mCaps, mRenderer, framebuffer);
-    }
-
-    mState.setDrawFramebufferBinding(getFramebuffer(framebuffer));
+    Framebuffer *framebuffer = checkFramebufferAllocation(framebufferHandle);
+    mState.setDrawFramebufferBinding(framebuffer);
 }
 
 void Context::bindRenderbuffer(GLuint renderbuffer)
 {
     mResourceManager->checkRenderbufferAllocation(renderbuffer);
 
     mState.setRenderbufferBinding(getRenderbuffer(renderbuffer));
 }
@@ -724,28 +817,78 @@ Error Context::endQuery(GLenum target)
     gl::Error error = queryObject->end();
 
     // Always unbind the query, even if there was an error. This may delete the query object.
     mState.setActiveQuery(target, NULL);
 
     return error;
 }
 
+Error Context::queryCounter(GLuint id, GLenum target)
+{
+    ASSERT(target == GL_TIMESTAMP_EXT);
+
+    Query *queryObject = getQuery(id, true, target);
+    ASSERT(queryObject);
+
+    return queryObject->queryCounter();
+}
+
+void Context::getQueryiv(GLenum target, GLenum pname, GLint *params)
+{
+    switch (pname)
+    {
+        case GL_CURRENT_QUERY_EXT:
+            params[0] = getState().getActiveQueryId(target);
+            break;
+        case GL_QUERY_COUNTER_BITS_EXT:
+            switch (target)
+            {
+                case GL_TIME_ELAPSED_EXT:
+                    params[0] = getExtensions().queryCounterBitsTimeElapsed;
+                    break;
+                case GL_TIMESTAMP_EXT:
+                    params[0] = getExtensions().queryCounterBitsTimestamp;
+                    break;
+                default:
+                    UNREACHABLE();
+                    params[0] = 0;
+                    break;
+            }
+            break;
+        default:
+            UNREACHABLE();
+            return;
+    }
+}
+
+Error Context::getQueryObjectiv(GLuint id, GLenum pname, GLint *params)
+{
+    return GetQueryObjectParameter(this, id, pname, params);
+}
+
+Error Context::getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
+{
+    return GetQueryObjectParameter(this, id, pname, params);
+}
+
+Error Context::getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params)
+{
+    return GetQueryObjectParameter(this, id, pname, params);
+}
+
+Error Context::getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params)
+{
+    return GetQueryObjectParameter(this, id, pname, params);
+}
+
 Framebuffer *Context::getFramebuffer(unsigned int handle) const
 {
-    FramebufferMap::const_iterator framebuffer = mFramebufferMap.find(handle);
-
-    if (framebuffer == mFramebufferMap.end())
-    {
-        return NULL;
-    }
-    else
-    {
-        return framebuffer->second;
-    }
+    auto framebufferIt = mFramebufferMap.find(handle);
+    return ((framebufferIt == mFramebufferMap.end()) ? nullptr : framebufferIt->second);
 }
 
 FenceNV *Context::getFenceNV(unsigned int handle)
 {
     FenceNVMap::iterator fence = mFenceNVMap.find(handle);
 
     if (fence == mFenceNVMap.end())
     {
@@ -771,21 +914,26 @@ Query *Context::getQuery(unsigned int ha
         {
             query->second = new Query(mRenderer->createQuery(type), handle);
             query->second->addRef();
         }
         return query->second;
     }
 }
 
+Query *Context::getQuery(GLuint handle) const
+{
+    auto iter = mQueryMap.find(handle);
+    return (iter != mQueryMap.end()) ? iter->second : nullptr;
+}
+
 Texture *Context::getTargetTexture(GLenum target) const
 {
     ASSERT(ValidTextureTarget(this, target));
-
-    return getSamplerTexture(mState.getActiveSampler(), target);
+    return mState.getTargetTexture(target);
 }
 
 Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const
 {
     return mState.getSamplerTexture(sampler, type);
 }
 
 Compiler *Context::getCompiler() const
@@ -900,16 +1048,36 @@ void Context::getIntegerv(GLenum pname, 
           *params = static_cast<GLint>(mCaps.programBinaryFormats.size());
         break;
       case GL_PROGRAM_BINARY_FORMATS:
         std::copy(mCaps.programBinaryFormats.begin(), mCaps.programBinaryFormats.end(), params);
         break;
       case GL_NUM_EXTENSIONS:
         *params = static_cast<GLint>(mExtensionStrings.size());
         break;
+
+      // GL_KHR_debug
+      case GL_MAX_DEBUG_MESSAGE_LENGTH:
+          *params = mExtensions.maxDebugMessageLength;
+          break;
+      case GL_MAX_DEBUG_LOGGED_MESSAGES:
+          *params = mExtensions.maxDebugLoggedMessages;
+          break;
+      case GL_MAX_DEBUG_GROUP_STACK_DEPTH:
+          *params = mExtensions.maxDebugGroupStackDepth;
+          break;
+      case GL_MAX_LABEL_LENGTH:
+          *params = mExtensions.maxLabelLength;
+          break;
+
+      // GL_EXT_disjoint_timer_query
+      case GL_GPU_DISJOINT_EXT:
+          *params = mRenderer->getGPUDisjoint();
+          break;
+
       default:
         mState.getIntegerv(getData(), pname, params);
         break;
     }
 }
 
 void Context::getInteger64v(GLenum pname, GLint64 *params)
 {
@@ -927,22 +1095,32 @@ void Context::getInteger64v(GLenum pname
         *params = mCaps.maxCombinedVertexUniformComponents;
         break;
       case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
         *params = mCaps.maxCombinedFragmentUniformComponents;
         break;
       case GL_MAX_SERVER_WAIT_TIMEOUT:
         *params = mCaps.maxServerWaitTimeout;
         break;
+
+      // GL_EXT_disjoint_timer_query
+      case GL_TIMESTAMP_EXT:
+          *params = mRenderer->getTimestamp();
+          break;
       default:
         UNREACHABLE();
         break;
     }
 }
 
+void Context::getPointerv(GLenum pname, void **params) const
+{
+    mState.getPointerv(pname, params);
+}
+
 bool Context::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
 {
     // Queries about context capabilities and maximums are answered by Context.
     // Queries about current GL state values are answered by State.
     // Indexed integer queries all refer to current state, so this function is a
     // mere passthrough.
     return mState.getIndexedIntegerv(target, index, data);
 }
@@ -1142,16 +1320,55 @@ bool Context::getQueryParameterInfo(GLen
       case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
         if (!mExtensions.maxTextureAnisotropy)
         {
             return false;
         }
         *type = GL_FLOAT;
         *numParams = 1;
         return true;
+      case GL_TIMESTAMP_EXT:
+          if (!mExtensions.disjointTimerQuery)
+          {
+              return false;
+          }
+          *type      = GL_INT_64_ANGLEX;
+          *numParams = 1;
+          return true;
+      case GL_GPU_DISJOINT_EXT:
+          if (!mExtensions.disjointTimerQuery)
+          {
+              return false;
+          }
+          *type      = GL_INT;
+          *numParams = 1;
+          return true;
+    }
+
+    if (mExtensions.debug)
+    {
+        switch (pname)
+        {
+            case GL_DEBUG_LOGGED_MESSAGES:
+            case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
+            case GL_DEBUG_GROUP_STACK_DEPTH:
+            case GL_MAX_DEBUG_MESSAGE_LENGTH:
+            case GL_MAX_DEBUG_LOGGED_MESSAGES:
+            case GL_MAX_DEBUG_GROUP_STACK_DEPTH:
+            case GL_MAX_LABEL_LENGTH:
+                *type      = GL_INT;
+                *numParams = 1;
+                return true;
+
+            case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+            case GL_DEBUG_OUTPUT:
+                *type      = GL_BOOL;
+                *numParams = 1;
+                return true;
+        }
     }
 
     // Check for ES3.0+ parameter names which are also exposed as ES2 extensions
     switch (pname)
     {
         case GL_PACK_ROW_LENGTH:
         case GL_PACK_SKIP_ROWS:
         case GL_PACK_SKIP_PIXELS:
@@ -1388,16 +1605,23 @@ void Context::popGroupMarker()
     mRenderer->popGroupMarker();
 }
 
 void Context::recordError(const Error &error)
 {
     if (error.isError())
     {
         mErrors.insert(error.getCode());
+
+        if (!error.getMessage().empty())
+        {
+            auto &debug = mState.getDebug();
+            debug.insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, error.getID(),
+                                GL_DEBUG_SEVERITY_HIGH, error.getMessage());
+        }
     }
 }
 
 // Get one of the recorded errors and clear its flag, if any.
 // [OpenGL ES 2.0.24] section 2.5 page 13.
 GLenum Context::getError()
 {
     if (mErrors.empty())
@@ -1469,35 +1693,58 @@ EGLenum Context::getRenderBuffer() const
     else
     {
         return EGL_NONE;
     }
 }
 
 void Context::checkVertexArrayAllocation(GLuint vertexArray)
 {
+    // Only called after a prior call to Gen.
     if (!getVertexArray(vertexArray))
     {
         VertexArray *vertexArrayObject =
             new VertexArray(mRenderer, vertexArray, MAX_VERTEX_ATTRIBS);
         mVertexArrayMap[vertexArray] = vertexArrayObject;
     }
 }
 
 void Context::checkTransformFeedbackAllocation(GLuint transformFeedback)
 {
+    // Only called after a prior call to Gen.
     if (!getTransformFeedback(transformFeedback))
     {
         TransformFeedback *transformFeedbackObject =
             new TransformFeedback(mRenderer->createTransformFeedback(), transformFeedback, mCaps);
         transformFeedbackObject->addRef();
         mTransformFeedbackMap[transformFeedback] = transformFeedbackObject;
     }
 }
 
+Framebuffer *Context::checkFramebufferAllocation(GLuint framebuffer)
+{
+    // Can be called from Bind without a prior call to Gen.
+    auto framebufferIt = mFramebufferMap.find(framebuffer);
+    bool neverCreated = framebufferIt == mFramebufferMap.end();
+    if (neverCreated || framebufferIt->second == nullptr)
+    {
+        Framebuffer *newFBO = new Framebuffer(mCaps, mRenderer, framebuffer);
+        if (neverCreated)
+        {
+            mFramebufferHandleAllocator.reserve(framebuffer);
+            mFramebufferMap[framebuffer] = newFBO;
+            return newFBO;
+        }
+
+        framebufferIt->second = newFBO;
+    }
+
+    return framebufferIt->second;
+}
+
 bool Context::isVertexArrayGenerated(GLuint vertexArray)
 {
     return mVertexArrayMap.find(vertexArray) != mVertexArrayMap.end();
 }
 
 bool Context::isTransformFeedbackGenerated(GLuint transformFeedback)
 {
     return mTransformFeedbackMap.find(transformFeedback) != mTransformFeedbackMap.end();
@@ -1735,16 +1982,23 @@ void Context::initCaps(GLuint clientVers
     }
 
     if (clientVersion > 2)
     {
         // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts
         //mExtensions.sRGB = false;
     }
 
+    // Explicitly enable GL_KHR_debug
+    mExtensions.debug                   = true;
+    mExtensions.maxDebugMessageLength   = 1024;
+    mExtensions.maxDebugLoggedMessages  = 1024;
+    mExtensions.maxDebugGroupStackDepth = 1024;
+    mExtensions.maxLabelLength          = 1024;
+
     // Apply implementation limits
     mCaps.maxVertexAttributes = std::min<GLuint>(mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS);
     mCaps.maxVertexUniformBlocks = std::min<GLuint>(mCaps.maxVertexUniformBlocks, IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS);
     mCaps.maxVertexOutputComponents = std::min<GLuint>(mCaps.maxVertexOutputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
 
     mCaps.maxFragmentInputComponents = std::min<GLuint>(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
 
     mCaps.compressedTextureFormats.clear();
@@ -1780,25 +2034,391 @@ void Context::initCaps(GLuint clientVers
 
         mTextureCaps.insert(format, formatCaps);
     }
 }
 
 void Context::syncRendererState()
 {
     const State::DirtyBits &dirtyBits = mState.getDirtyBits();
-    if (dirtyBits.any())
-    {
-        mRenderer->syncState(mState, dirtyBits);
-        mState.clearDirtyBits();
-    }
+    mRenderer->syncState(mState, dirtyBits);
+    mState.clearDirtyBits();
+    mState.syncDirtyObjects();
 }
 
 void Context::syncRendererState(const State::DirtyBits &bitMask)
 {
     const State::DirtyBits &dirtyBits = (mState.getDirtyBits() & bitMask);
-    if (dirtyBits.any())
+    mRenderer->syncState(mState, dirtyBits);
+    mState.clearDirtyBits(dirtyBits);
+
+    // TODO(jmadill): Filter objects by bitMask somehow?
+    mState.syncDirtyObjects();
+}
+
+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();
+    ASSERT(readFramebuffer);
+
+    Framebuffer *drawFramebuffer = mState.getDrawFramebuffer();
+    ASSERT(drawFramebuffer);
+
+    Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
+    Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
+
+    syncRendererState(mState.blitStateBitMask());
+
+    Error error = drawFramebuffer->blit(mState, srcArea, dstArea, mask, filter, readFramebuffer);
+    if (error.isError())
+    {
+        recordError(error);
+        return;
+    }
+}
+
+void Context::clear(GLbitfield mask)
+{
+    // Sync the clear state
+    syncRendererState(mState.clearStateBitMask());
+
+    Error error = mState.getDrawFramebuffer()->clear(mData, mask);
+    if (error.isError())
+    {
+        recordError(error);
+    }
+}
+
+void Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values)
+{
+    // Sync the clear state
+    syncRendererState(mState.clearStateBitMask());
+
+    Error error = mState.getDrawFramebuffer()->clearBufferfv(mData, buffer, drawbuffer, values);
+    if (error.isError())
+    {
+        recordError(error);
+    }
+}
+
+void Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values)
+{
+    // Sync the clear state
+    syncRendererState(mState.clearStateBitMask());
+
+    Error error = mState.getDrawFramebuffer()->clearBufferuiv(mData, buffer, drawbuffer, values);
+    if (error.isError())
+    {
+        recordError(error);
+    }
+}
+
+void Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values)
+{
+    // Sync the clear state
+    syncRendererState(mState.clearStateBitMask());
+
+    Error error = mState.getDrawFramebuffer()->clearBufferiv(mData, buffer, drawbuffer, values);
+    if (error.isError())
     {
-        mRenderer->syncState(mState, dirtyBits);
-        mState.clearDirtyBits(dirtyBits);
+        recordError(error);
+    }
+}
+
+void Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+{
+    Framebuffer *framebufferObject = mState.getDrawFramebuffer();
+    ASSERT(framebufferObject);
+
+    // If a buffer is not present, the clear has no effect
+    if (framebufferObject->getDepthbuffer() == nullptr &&
+        framebufferObject->getStencilbuffer() == nullptr)
+    {
+        return;
+    }
+
+    // Sync the clear state
+    syncRendererState(mState.clearStateBitMask());
+
+    Error error = framebufferObject->clearBufferfi(mData, buffer, drawbuffer, depth, stencil);
+    if (error.isError())
+    {
+        recordError(error);
+    }
+}
+
+void Context::readPixels(GLint x,
+                         GLint y,
+                         GLsizei width,
+                         GLsizei height,
+                         GLenum format,
+                         GLenum type,
+                         GLvoid *pixels)
+{
+    // Sync pack state
+    syncRendererState(mState.packStateBitMask());
+
+    Framebuffer *framebufferObject = mState.getReadFramebuffer();
+    ASSERT(framebufferObject);
+
+    Rectangle area(x, y, width, height);
+    Error error = framebufferObject->readPixels(mState, area, format, type, pixels);
+    if (error.isError())
+    {
+        recordError(error);
+    }
+}
+
+void Context::copyTexImage2D(GLenum target,
+                             GLint level,
+                             GLenum internalformat,
+                             GLint x,
+                             GLint y,
+                             GLsizei width,
+                             GLsizei height,
+                             GLint border)
+{
+    // Only sync the read FBO
+    mState.syncDirtyObject(GL_READ_FRAMEBUFFER);
+
+    Rectangle sourceArea(x, y, width, height);
+
+    const Framebuffer *framebuffer = mState.getReadFramebuffer();
+    Texture *texture =
+        getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+    Error error = texture->copyImage(target, level, sourceArea, internalformat, framebuffer);
+    if (error.isError())
+    {
+        recordError(error);
+    }
+}
+
+void Context::copyTexSubImage2D(GLenum target,
+                                GLint level,
+                                GLint xoffset,
+                                GLint yoffset,
+                                GLint x,
+                                GLint y,
+                                GLsizei width,
+                                GLsizei height)
+{
+    // Only sync the read FBO
+    mState.syncDirtyObject(GL_READ_FRAMEBUFFER);
+
+    Offset destOffset(xoffset, yoffset, 0);
+    Rectangle sourceArea(x, y, width, height);
+
+    const Framebuffer *framebuffer = mState.getReadFramebuffer();
+    Texture *texture =
+        getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+    Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer);
+    if (error.isError())
+    {
+        recordError(error);
     }
 }
+
+void Context::copyTexSubImage3D(GLenum target,
+                                GLint level,
+                                GLint xoffset,
+                                GLint yoffset,
+                                GLint zoffset,
+                                GLint x,
+                                GLint y,
+                                GLsizei width,
+                                GLsizei height)
+{
+    // Only sync the read FBO
+    mState.syncDirtyObject(GL_READ_FRAMEBUFFER);
+
+    Offset destOffset(xoffset, yoffset, zoffset);
+    Rectangle sourceArea(x, y, width, height);
+
+    const Framebuffer *framebuffer = mState.getReadFramebuffer();
+    Texture *texture               = getTargetTexture(target);
+    Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer);
+    if (error.isError())
+    {
+        recordError(error);
+    }
 }
+
+void Context::framebufferTexture2D(GLenum target,
+                                   GLenum attachment,
+                                   GLenum textarget,
+                                   GLuint texture,
+                                   GLint level)
+{
+    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (texture != 0)
+    {
+        Texture *textureObj = getTexture(texture);
+
+        ImageIndex index = ImageIndex::MakeInvalid();
+
+        if (textarget == GL_TEXTURE_2D)
+        {
+            index = ImageIndex::Make2D(level);
+        }
+        else
+        {
+            ASSERT(IsCubeMapTextureTarget(textarget));
+            index = ImageIndex::MakeCube(textarget, level);
+        }
+
+        framebuffer->setAttachment(GL_TEXTURE, attachment, index, textureObj);
+    }
+    else
+    {
+        framebuffer->resetAttachment(attachment);
+    }
+
+    mState.setObjectDirty(target);
+}
+
+void Context::framebufferRenderbuffer(GLenum target,
+                                      GLenum attachment,
+                                      GLenum renderbuffertarget,
+                                      GLuint renderbuffer)
+{
+    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (renderbuffer != 0)
+    {
+        Renderbuffer *renderbufferObject = getRenderbuffer(renderbuffer);
+        framebuffer->setAttachment(GL_RENDERBUFFER, attachment, gl::ImageIndex::MakeInvalid(),
+                                   renderbufferObject);
+    }
+    else
+    {
+        framebuffer->resetAttachment(attachment);
+    }
+
+    mState.setObjectDirty(target);
+}
+
+void Context::framebufferTextureLayer(GLenum target,
+                                      GLenum attachment,
+                                      GLuint texture,
+                                      GLint level,
+                                      GLint layer)
+{
+    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (texture != 0)
+    {
+        Texture *textureObject = getTexture(texture);
+
+        ImageIndex index = ImageIndex::MakeInvalid();
+
+        if (textureObject->getTarget() == GL_TEXTURE_3D)
+        {
+            index = ImageIndex::Make3D(level, layer);
+        }
+        else
+        {
+            ASSERT(textureObject->getTarget() == GL_TEXTURE_2D_ARRAY);
+            index = ImageIndex::Make2DArray(level, layer);
+        }
+
+        framebuffer->setAttachment(GL_TEXTURE, attachment, index, textureObject);
+    }
+    else
+    {
+        framebuffer->resetAttachment(attachment);
+    }
+
+    mState.setObjectDirty(target);
+}
+
+void Context::drawBuffers(GLsizei n, const GLenum *bufs)
+{
+    Framebuffer *framebuffer = mState.getDrawFramebuffer();
+    ASSERT(framebuffer);
+    framebuffer->setDrawBuffers(n, bufs);
+    mState.setObjectDirty(GL_DRAW_FRAMEBUFFER);
+}
+
+void Context::readBuffer(GLenum mode)
+{
+    Framebuffer *readFBO = mState.getReadFramebuffer();
+    readFBO->setReadBuffer(mode);
+    mState.setObjectDirty(GL_READ_FRAMEBUFFER);
+}
+
+void Context::discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)
+{
+    // Only sync the FBO
+    mState.syncDirtyObject(target);
+
+    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    // The specification isn't clear what should be done when the framebuffer isn't complete.
+    // We leave it up to the framebuffer implementation to decide what to do.
+    Error error = framebuffer->discard(numAttachments, attachments);
+    if (error.isError())
+    {
+        recordError(error);
+    }
+}
+
+void Context::invalidateFramebuffer(GLenum target,
+                                    GLsizei numAttachments,
+                                    const GLenum *attachments)
+{
+    // Only sync the FBO
+    mState.syncDirtyObject(target);
+
+    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (framebuffer->checkStatus(mData) == GL_FRAMEBUFFER_COMPLETE)
+    {
+        Error error = framebuffer->invalidate(numAttachments, attachments);
+        if (error.isError())
+        {
+            recordError(error);
+            return;
+        }
+    }
+}
+
+void Context::invalidateSubFramebuffer(GLenum target,
+                                       GLsizei numAttachments,
+                                       const GLenum *attachments,
+                                       GLint x,
+                                       GLint y,
+                                       GLsizei width,
+                                       GLsizei height)
+{
+    // Only sync the FBO
+    mState.syncDirtyObject(target);
+
+    Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+    ASSERT(framebuffer);
+
+    if (framebuffer->checkStatus(mData) == GL_FRAMEBUFFER_COMPLETE)
+    {
+        Rectangle area(x, y, width, height);
+        Error error = framebuffer->invalidateSub(numAttachments, attachments, area);
+        if (error.isError())
+        {
+            recordError(error);
+            return;
+        }
+    }
+}
+
+}  // namespace gl
--- a/gfx/angle/src/libANGLE/Context.h
+++ b/gfx/angle/src/libANGLE/Context.h
@@ -28,16 +28,17 @@
 
 namespace rx
 {
 class Renderer;
 }
 
 namespace egl
 {
+class AttributeMap;
 class Surface;
 struct Config;
 }
 
 namespace gl
 {
 class Compiler;
 class Shader;
@@ -53,17 +54,20 @@ class Buffer;
 struct VertexAttribute;
 class VertexArray;
 class Sampler;
 class TransformFeedback;
 
 class Context final : public ValidationContext
 {
   public:
-    Context(const egl::Config *config, int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
+    Context(const egl::Config *config,
+            const Context *shareContext,
+            rx::Renderer *renderer,
+            const egl::AttributeMap &attribs);
 
     virtual ~Context();
 
     void makeCurrent(egl::Surface *surface);
     void releaseSurface();
 
     virtual void markContextLost();
     bool isContextLost();
@@ -102,76 +106,92 @@ class Context final : public ValidationC
 
     // Vertex arrays are owned by the Context
     GLuint createVertexArray();
     void deleteVertexArray(GLuint vertexArray);
 
     void bindArrayBuffer(GLuint buffer);
     void bindElementArrayBuffer(GLuint buffer);
     void bindTexture(GLenum target, GLuint handle);
-    void bindReadFramebuffer(GLuint framebuffer);
-    void bindDrawFramebuffer(GLuint framebuffer);
+    void bindReadFramebuffer(GLuint framebufferHandle);
+    void bindDrawFramebuffer(GLuint framebufferHandle);
     void bindRenderbuffer(GLuint renderbuffer);
     void bindVertexArray(GLuint vertexArray);
     void bindSampler(GLuint textureUnit, GLuint sampler);
     void bindGenericUniformBuffer(GLuint buffer);
     void bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size);
     void bindGenericTransformFeedbackBuffer(GLuint buffer);
     void bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size);
     void bindCopyReadBuffer(GLuint buffer);
     void bindCopyWriteBuffer(GLuint buffer);
     void bindPixelPackBuffer(GLuint buffer);
     void bindPixelUnpackBuffer(GLuint buffer);
     void useProgram(GLuint program);
     void bindTransformFeedback(GLuint transformFeedback);
 
     Error beginQuery(GLenum target, GLuint query);
     Error endQuery(GLenum target);
+    Error queryCounter(GLuint id, GLenum target);
+    void getQueryiv(GLenum target, GLenum pname, GLint *params);
+    Error getQueryObjectiv(GLuint id, GLenum pname, GLint *params);
+    Error getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params);
+    Error getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params);
+    Error getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params);
 
     void setVertexAttribDivisor(GLuint index, GLuint divisor);
 
     void samplerParameteri(GLuint sampler, GLenum pname, GLint param);
     void samplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
     GLint getSamplerParameteri(GLuint sampler, GLenum pname);
     GLfloat getSamplerParameterf(GLuint sampler, GLenum pname);
 
-    Buffer *getBuffer(GLuint handle);
+    Buffer *getBuffer(GLuint handle) const;
     FenceNV *getFenceNV(GLuint handle);
     FenceSync *getFenceSync(GLsync handle) const;
     Shader *getShader(GLuint handle) const;
     Program *getProgram(GLuint handle) const;
     Texture *getTexture(GLuint handle) const;
     Framebuffer *getFramebuffer(GLuint handle) const;
-    Renderbuffer *getRenderbuffer(GLuint handle);
+    Renderbuffer *getRenderbuffer(GLuint handle) const;
     VertexArray *getVertexArray(GLuint handle) const;
     Sampler *getSampler(GLuint handle) const;
     Query *getQuery(GLuint handle, bool create, GLenum type);
+    Query *getQuery(GLuint handle) const;
     TransformFeedback *getTransformFeedback(GLuint handle) const;
+    LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const;
+    LabeledObject *getLabeledObjectFromPtr(const void *ptr) const;
 
     Texture *getTargetTexture(GLenum target) const;
     Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
 
     Compiler *getCompiler() const;
 
     bool isSampler(GLuint samplerName) const;
 
     bool isVertexArrayGenerated(GLuint vertexArray);
     bool isTransformFeedbackGenerated(GLuint vertexArray);
 
     void getBooleanv(GLenum pname, GLboolean *params);
     void getFloatv(GLenum pname, GLfloat *params);
     void getIntegerv(GLenum pname, GLint *params);
     void getInteger64v(GLenum pname, GLint64 *params);
+    void getPointerv(GLenum pname, void **params) const;
 
     bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data);
     bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data);
 
     bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
     bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams);
 
+    void clear(GLbitfield mask);
+    void clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values);
+    void clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values);
+    void clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values);
+    void clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+
     Error drawArrays(GLenum mode, GLint first, GLsizei count);
     Error drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
 
     Error drawElements(GLenum mode,
                        GLsizei count,
                        GLenum type,
                        const GLvoid *indices,
                        const IndexRange &indexRange);
@@ -184,16 +204,93 @@ class Context final : public ValidationC
     Error drawRangeElements(GLenum mode,
                             GLuint start,
                             GLuint end,
                             GLsizei count,
                             GLenum type,
                             const GLvoid *indices,
                             const IndexRange &indexRange);
 
+    void blitFramebuffer(GLint srcX0,
+                         GLint srcY0,
+                         GLint srcX1,
+                         GLint srcY1,
+                         GLint dstX0,
+                         GLint dstY0,
+                         GLint dstX1,
+                         GLint dstY1,
+                         GLbitfield mask,
+                         GLenum filter);
+
+    void readPixels(GLint x,
+                    GLint y,
+                    GLsizei width,
+                    GLsizei height,
+                    GLenum format,
+                    GLenum type,
+                    GLvoid *pixels);
+
+    void copyTexImage2D(GLenum target,
+                        GLint level,
+                        GLenum internalformat,
+                        GLint x,
+                        GLint y,
+                        GLsizei width,
+                        GLsizei height,
+                        GLint border);
+
+    void copyTexSubImage2D(GLenum target,
+                           GLint level,
+                           GLint xoffset,
+                           GLint yoffset,
+                           GLint x,
+                           GLint y,
+                           GLsizei width,
+                           GLsizei height);
+
+    void copyTexSubImage3D(GLenum target,
+                           GLint level,
+                           GLint xoffset,
+                           GLint yoffset,
+                           GLint zoffset,
+                           GLint x,
+                           GLint y,
+                           GLsizei width,
+                           GLsizei height);
+
+    void framebufferTexture2D(GLenum target,
+                              GLenum attachment,
+                              GLenum textarget,
+                              GLuint texture,
+                              GLint level);
+
+    void framebufferRenderbuffer(GLenum target,
+                                 GLenum attachment,
+                                 GLenum renderbuffertarget,
+                                 GLuint renderbuffer);
+
+    void framebufferTextureLayer(GLenum target,
+                                 GLenum attachment,
+                                 GLuint texture,
+                                 GLint level,
+                                 GLint layer);
+
+    void drawBuffers(GLsizei n, const GLenum *bufs);
+    void readBuffer(GLenum mode);
+
+    void discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments);
+    void invalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments);
+    void invalidateSubFramebuffer(GLenum target,
+                                  GLsizei numAttachments,
+                                  const GLenum *attachments,
+                                  GLint x,
+                                  GLint y,
+                                  GLsizei width,
+                                  GLsizei height);
+
     Error flush();
     Error finish();
 
     void insertEventMarker(GLsizei length, const char *marker);
     void pushGroupMarker(GLsizei length, const char *marker);
     void popGroupMarker();
 
     void recordError(const Error &error) override;
@@ -217,16 +314,17 @@ class Context final : public ValidationC
     State &getState() { return mState; }
 
     void syncRendererState();
     void syncRendererState(const State::DirtyBits &bitMask);
 
   private:
     void checkVertexArrayAllocation(GLuint vertexArray);
     void checkTransformFeedbackAllocation(GLuint transformFeedback);
+    Framebuffer *checkFramebufferAllocation(GLuint framebufferHandle);
 
     void detachBuffer(GLuint buffer);
     void detachTexture(GLuint texture);
     void detachFramebuffer(GLuint framebuffer);
     void detachRenderbuffer(GLuint renderbuffer);
     void detachVertexArray(GLuint vertexArray);
     void detachTransformFeedback(GLuint transformFeedback);
     void detachSampler(GLuint sampler);
@@ -289,11 +387,11 @@ class Context final : public ValidationC
     GLenum mResetStatus;
     GLenum mResetStrategy;
     bool mRobustAccess;
     egl::Surface *mCurrentSurface;
 
     ResourceManager *mResourceManager;
 };
 
-}
+}  // namespace gl
 
 #endif   // LIBANGLE_CONTEXT_H_
--- a/gfx/angle/src/libANGLE/Data.cpp
+++ b/gfx/angle/src/libANGLE/Data.cpp
@@ -35,20 +35,22 @@ Data::~Data()
 }
 
 ValidationContext::ValidationContext(GLint clientVersion,
                                      const State &state,
                                      const Caps &caps,
                                      const TextureCapsMap &textureCaps,
                                      const Extensions &extensions,
                                      const ResourceManager *resourceManager,
-                                     const Limitations &limitations)
+                                     const Limitations &limitations,
+                                     bool skipValidation)
     : mData(reinterpret_cast<uintptr_t>(this),
             clientVersion,
             state,
             caps,
             textureCaps,
             extensions,
             resourceManager,
-            limitations)
+            limitations),
+      mSkipValidation(skipValidation)
 {
 }
-}
+}  // namespace gl
--- a/gfx/angle/src/libANGLE/Data.h
+++ b/gfx/angle/src/libANGLE/Data.h
@@ -42,28 +42,31 @@ class ValidationContext : angle::NonCopy
 {
   public:
     ValidationContext(GLint clientVersion,
                       const State &state,
                       const Caps &caps,
                       const TextureCapsMap &textureCaps,
                       const Extensions &extensions,
                       const ResourceManager *resourceManager,
-                      const Limitations &limitations);
+                      const Limitations &limitations,
+                      bool skipValidation);
     virtual ~ValidationContext() {}
 
     virtual void recordError(const Error &error) = 0;
 
     const Data &getData() const { return mData; }
     int getClientVersion() const { return mData.clientVersion; }
     const State &getState() const { return *mData.state; }
     const Caps &getCaps() const { return *mData.caps; }
     const TextureCapsMap &getTextureCaps() const { return *mData.textureCaps; }
     const Extensions &getExtensions() const { return *mData.extensions; }
     const Limitations &getLimitations() const { return *mData.limitations; }
+    bool skipValidation() const { return mSkipValidation; }
 
   protected:
     Data mData;
+    bool mSkipValidation;
 };
 
 }
 
 #endif // LIBANGLE_DATA_H_
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Debug.cpp
@@ -0,0 +1,303 @@
+//
+// Copyright (c) 2015 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.
+//
+
+// Debug.cpp: Defines debug state used for GL_KHR_debug
+
+#include "libANGLE/Debug.h"
+
+#include "common/debug.h"
+
+#include <algorithm>
+#include <tuple>
+
+namespace gl
+{
+
+Debug::Debug()
+    : mOutputEnabled(false),
+      mCallbackFunction(nullptr),
+      mCallbackUserParam(nullptr),
+      mMessages(),
+      mMaxLoggedMessages(0),
+      mOutputSynchronous(false),
+      mGroups()
+{
+    pushDefaultGroup();
+}
+
+void Debug::setMaxLoggedMessages(GLuint maxLoggedMessages)
+{
+    mMaxLoggedMessages = maxLoggedMessages;
+}
+
+void Debug::setOutputEnabled(bool enabled)
+{
+    mOutputEnabled = enabled;
+}
+
+bool Debug::isOutputEnabled() const
+{
+    return mOutputEnabled;
+}
+
+void Debug::setOutputSynchronous(bool synchronous)
+{
+    mOutputSynchronous = synchronous;
+}
+
+bool Debug::isOutputSynchronous() const
+{
+    return mOutputSynchronous;
+}
+
+void Debug::setCallback(GLDEBUGPROCKHR callback, const void *userParam)
+{
+    mCallbackFunction  = callback;
+    mCallbackUserParam = userParam;
+}
+
+GLDEBUGPROCKHR Debug::getCallback() const
+{
+    return mCallbackFunction;
+}
+
+const void *Debug::getUserParam() const
+{
+    return mCallbackUserParam;
+}
+
+void Debug::insertMessage(GLenum source,
+                          GLenum type,
+                          GLuint id,
+                          GLenum severity,
+                          const std::string &message)
+{
+    std::string messageCopy(message);
+    insertMessage(source, type, id, severity, std::move(messageCopy));
+}
+
+void Debug::insertMessage(GLenum source,
+                          GLenum type,
+                          GLuint id,
+                          GLenum severity,
+                          std::string &&message)
+{
+    if (!isMessageEnabled(source, type, id, severity))
+    {
+        return;
+    }
+
+    if (mCallbackFunction != nullptr)
+    {
+        // TODO(geofflang) Check the synchronous flag and potentially flush messages from another
+        // thread.
+        mCallbackFunction(source, type, id, severity, static_cast<GLsizei>(message.length()),
+                          message.c_str(), mCallbackUserParam);
+    }
+    else
+    {
+        if (mMessages.size() >= mMaxLoggedMessages)
+        {
+            // Drop messages over the limit
+            return;
+        }
+
+        Message m;
+        m.source   = source;
+        m.type     = type;
+        m.id       = id;
+        m.severity = severity;
+        m.message  = std::move(message);
+
+        mMessages.push_back(std::move(m));
+    }
+}
+
+size_t Debug::getMessages(GLuint count,
+                          GLsizei bufSize,
+                          GLenum *sources,
+                          GLenum *types,
+                          GLuint *ids,
+                          GLenum *severities,
+                          GLsizei *lengths,
+                          GLchar *messageLog)
+{
+    size_t messageCount       = 0;
+    size_t messageStringIndex = 0;
+    while (messageCount <= count && !mMessages.empty())
+    {
+        const Message &m = mMessages.front();
+
+        if (messageLog != nullptr)
+        {
+            // Check that this message can fit in the message buffer
+            if (messageStringIndex + m.message.length() + 1 > static_cast<size_t>(bufSize))
+            {
+                break;
+            }
+
+            std::copy(m.message.begin(), m.message.end(), messageLog + messageStringIndex);
+            messageStringIndex += m.message.length();
+
+            messageLog[messageStringIndex] = '\0';
+            messageStringIndex += 1;
+        }
+
+        if (sources != nullptr)
+        {
+            sources[messageCount] = m.source;
+        }
+
+        if (types != nullptr)
+        {
+            types[messageCount] = m.type;
+        }
+
+        if (ids != nullptr)
+        {
+            ids[messageCount] = m.id;
+        }
+
+        if (severities != nullptr)
+        {
+            severities[messageCount] = m.severity;
+        }
+
+        if (lengths != nullptr)
+        {
+            lengths[messageCount] = static_cast<GLsizei>(m.message.length());
+        }
+
+        mMessages.pop_front();
+
+        messageCount++;
+    }
+
+    return messageCount;
+}
+
+size_t Debug::getNextMessageLength() const
+{
+    return mMessages.empty() ? 0 : mMessages.front().message.length();
+}
+
+size_t Debug::getMessageCount() const
+{
+    return mMessages.size();
+}
+
+void Debug::setMessageControl(GLenum source,
+                              GLenum type,
+                              GLenum severity,
+                              std::vector<GLuint> &&ids,
+                              bool enabled)
+{
+    Control c;
+    c.source   = source;
+    c.type     = type;
+    c.severity = severity;
+    c.ids      = std::move(ids);
+    c.enabled  = enabled;
+
+    auto &controls = mGroups.back().controls;
+    controls.push_back(std::move(c));
+}
+
+void Debug::pushGroup(GLenum source, GLuint id, std::string &&message)
+{
+    insertMessage(source, GL_DEBUG_TYPE_PUSH_GROUP, id, GL_DEBUG_SEVERITY_NOTIFICATION,
+                  std::string(message));
+
+    Group g;
+    g.source  = source;
+    g.id      = id;
+    g.message = std::move(message);
+    mGroups.push_back(std::move(g));
+}
+
+void Debug::popGroup()
+{
+    // Make sure the default group is not about to be popped
+    ASSERT(mGroups.size() > 1);
+
+    Group g = mGroups.back();
+    mGroups.pop_back();
+
+    insertMessage(g.source, GL_DEBUG_TYPE_POP_GROUP, g.id, GL_DEBUG_SEVERITY_NOTIFICATION,
+                  g.message);
+}
+
+size_t Debug::getGroupStackDepth() const
+{
+    return mGroups.size();
+}
+
+bool Debug::isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const
+{
+    if (!mOutputEnabled)
+    {
+        return false;
+    }
+
+    for (auto groupIter = mGroups.rbegin(); groupIter != mGroups.rend(); groupIter++)
+    {
+        const auto &controls = groupIter->controls;
+        for (auto controlIter = controls.rbegin(); controlIter != controls.rend(); controlIter++)
+        {
+            const auto &control = *controlIter;
+
+            if (control.source != GL_DONT_CARE && control.source != source)
+            {
+                continue;
+            }
+
+            if (control.type != GL_DONT_CARE && control.type != type)
+            {
+                continue;
+            }
+
+            if (control.severity != GL_DONT_CARE && control.severity != severity)
+            {
+                continue;
+            }
+
+            if (!control.ids.empty() &&
+                std::find(control.ids.begin(), control.ids.end(), id) == control.ids.end())
+            {
+                continue;
+            }
+
+            return control.enabled;
+        }
+    }
+
+    return true;
+}
+
+void Debug::pushDefaultGroup()
+{
+    Group g;
+    g.source  = GL_NONE;
+    g.id      = 0;
+    g.message = "";
+
+    Control c0;
+    c0.source   = GL_DONT_CARE;
+    c0.type     = GL_DONT_CARE;
+    c0.severity = GL_DONT_CARE;
+    c0.enabled = true;
+    g.controls.push_back(std::move(c0));
+
+    Control c1;
+    c1.source   = GL_DONT_CARE;
+    c1.type     = GL_DONT_CARE;
+    c1.severity = GL_DEBUG_SEVERITY_LOW;
+    c1.enabled = false;
+    g.controls.push_back(std::move(c1));
+
+    mGroups.push_back(std::move(g));
+}
+}  // namespace gl
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Debug.h
@@ -0,0 +1,120 @@
+//
+// Copyright (c) 2015 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.
+//
+
+// Debug.h: Defines debug state used for GL_KHR_debug
+
+#ifndef LIBANGLE_DEBUG_H_
+#define LIBANGLE_DEBUG_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+
+#include <deque>
+#include <string>
+#include <vector>
+
+namespace gl
+{
+
+class LabeledObject
+{
+  public:
+    virtual ~LabeledObject() {}
+    virtual void setLabel(const std::string &label) = 0;
+    virtual const std::string &getLabel() const = 0;
+};
+
+class Debug : angle::NonCopyable
+{
+  public:
+    Debug();
+
+    void setMaxLoggedMessages(GLuint maxLoggedMessages);
+
+    void setOutputEnabled(bool enabled);
+    bool isOutputEnabled() const;
+
+    void setOutputSynchronous(bool synchronous);
+    bool isOutputSynchronous() const;
+
+    void setCallback(GLDEBUGPROCKHR callback, const void *userParam);
+    GLDEBUGPROCKHR getCallback() const;
+    const void *getUserParam() const;
+
+    void insertMessage(GLenum source,
+                       GLenum type,
+                       GLuint id,
+                       GLenum severity,
+                       const std::string &message);
+    void insertMessage(GLenum source,
+                       GLenum type,
+                       GLuint id,
+                       GLenum severity,
+                       std::string &&message);
+
+    void setMessageControl(GLenum source,
+                           GLenum type,
+                           GLenum severity,
+                           std::vector<GLuint> &&ids,
+                           bool enabled);
+    size_t getMessages(GLuint count,
+                       GLsizei bufSize,
+                       GLenum *sources,
+                       GLenum *types,
+                       GLuint *ids,
+                       GLenum *severities,
+                       GLsizei *lengths,
+                       GLchar *messageLog);
+    size_t getNextMessageLength() const;
+    size_t getMessageCount() const;
+
+    void pushGroup(GLenum source, GLuint id, std::string &&message);
+    void popGroup();
+    size_t getGroupStackDepth() const;
+
+  private:
+    bool isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const;
+
+    void pushDefaultGroup();
+
+    struct Message
+    {
+        GLenum source;
+        GLenum type;
+        GLuint id;
+        GLenum severity;
+        std::string message;
+    };
+
+    struct Control
+    {
+        GLenum source;
+        GLenum type;
+        GLenum severity;
+        std::vector<GLuint> ids;
+        bool enabled;
+    };
+
+    struct Group
+    {
+        GLenum source;
+        GLuint id;
+        std::string message;
+
+        std::vector<Control> controls;
+    };
+
+    bool mOutputEnabled;
+    GLDEBUGPROCKHR mCallbackFunction;
+    const void *mCallbackUserParam;
+    std::deque<Message> mMessages;
+    GLuint mMaxLoggedMessages;
+    bool mOutputSynchronous;
+    std::vector<Group> mGroups;
+};
+}  // namespace gl
+
+#endif  // LIBANGLE_DEBUG_H_
--- a/gfx/angle/src/libANGLE/Display.cpp
+++ b/gfx/angle/src/libANGLE/Display.cpp
@@ -171,35 +171,47 @@ rx::DisplayImpl *CreateDisplayFromAttrib
 #else
 #error Unsupported OpenGL platform.
 #endif
 #else
         UNREACHABLE();
 #endif
         break;
 
+#if defined(ANGLE_ENABLE_OPENGL)
+      case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+#if defined(ANGLE_PLATFORM_WINDOWS)
+          impl = new rx::DisplayWGL();
+#elif defined(ANGLE_USE_X11)
+          impl = new rx::DisplayGLX();
+#else
+          // No GLES support on this platform, fail display creation.
+          impl = nullptr;
+#endif
+          break;
+#endif
+
       default:
         UNREACHABLE();
         break;
     }
 
-    ASSERT(impl != nullptr);
     return impl;
 }
 
 }
 
 Display *Display::GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap)
 {
     // Initialize the global platform if not already
     InitDefaultPlatformImpl();
 
     Display *display = nullptr;
 
-    EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display);
+    EGLNativeDisplayType displayId = reinterpret_cast<EGLNativeDisplayType>(native_display);
 
     ANGLEPlatformDisplayMap *displays            = GetANGLEPlatformDisplayMap();
     ANGLEPlatformDisplayMap::const_iterator iter = displays->find(displayId);
     if (iter != displays->end())
     {
         display = iter->second;
     }
 
@@ -214,16 +226,22 @@ Display *Display::GetDisplayFromAttribs(
         display = new Display(EGL_PLATFORM_ANGLE_ANGLE, displayId, nullptr);
         displays->insert(std::make_pair(displayId, display));
     }
 
     // Apply new attributes if the display is not initialized yet.
     if (!display->isInitialized())
     {
         rx::DisplayImpl *impl = CreateDisplayFromAttribs(attribMap);
+        if (impl == nullptr)
+        {
+            // No valid display implementation for these attributes
+            return nullptr;
+        }
+
         display->setAttributes(impl, attribMap);
     }
 
     return display;
 }
 
 Display *Display::GetDisplayFromDevice(void *native_display)
 {
@@ -478,16 +496,25 @@ bool Display::getConfigAttrib(const Conf
       case EGL_ALPHA_MASK_SIZE:           *value = configuration->alphaMaskSize;          break;
       case EGL_COLOR_BUFFER_TYPE:         *value = configuration->colorBufferType;        break;
       case EGL_RENDERABLE_TYPE:           *value = configuration->renderableType;         break;
       case EGL_MATCH_NATIVE_PIXMAP:       *value = false; UNIMPLEMENTED();                break;
       case EGL_CONFORMANT:                *value = configuration->conformant;             break;
       case EGL_MAX_PBUFFER_WIDTH:         *value = configuration->maxPBufferWidth;        break;
       case EGL_MAX_PBUFFER_HEIGHT:        *value = configuration->maxPBufferHeight;       break;
       case EGL_MAX_PBUFFER_PIXELS:        *value = configuration->maxPBufferPixels;       break;
+
+      case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+          if (!getExtensions().surfaceOrientation)
+          {
+              return false;
+          }
+          *value = configuration->optimalOrientation;
+          break;
+
       default:
         return false;
     }
 
     return true;
 }
 
 Error Display::createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs,
@@ -681,22 +708,18 @@ Error Display::createContext(const Confi
     {
         Error error = restoreLostDevice();
         if (error.isError())
         {
             return error;
         }
     }
 
-    gl::Context *context = nullptr;
-    Error error = mImplementation->createContext(configuration, shareContext, attribs, &context);
-    if (error.isError())
-    {
-        return error;
-    }
+    gl::Context *context = *outContext =
+        mImplementation->createContext(configuration, shareContext, attribs);
 
     ASSERT(context != nullptr);
     mContextSet.insert(context);
 
     ASSERT(outContext != nullptr);
     *outContext = context;
     return Error(EGL_SUCCESS);
 }
@@ -786,16 +809,26 @@ bool Display::testDeviceLost()
 void Display::notifyDeviceLost()
 {
     for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
     {
         (*context)->markContextLost();
     }
 }
 
+Error Display::waitClient() const
+{
+    return mImplementation->waitClient();
+}
+
+Error Display::waitNative(EGLint engine, egl::Surface *drawSurface, egl::Surface *readSurface) const
+{
+    return mImplementation->waitNative(engine, drawSurface, readSurface);
+}
+
 const Caps &Display::getCaps() const
 {
     return mCaps;
 }
 
 bool Display::isInitialized() const
 {
     return mInitialized;
@@ -844,16 +877,17 @@ static ClientExtensions GenerateClientEx
 
 #if defined(ANGLE_ENABLE_OPENGL)
     extensions.platformANGLEOpenGL = true;
 #endif
 
 #if defined(ANGLE_ENABLE_D3D11)
     extensions.deviceCreation      = true;
     extensions.deviceCreationD3D11 = true;
+    extensions.experimentalPresentPath = true;
 #endif
 
 #if defined(ANGLE_USE_X11)
     extensions.x11Visual = true;
 #endif
 
     extensions.clientGetAllProcAddresses = true;
 
--- a/gfx/angle/src/libANGLE/Display.h
+++ b/gfx/angle/src/libANGLE/Display.h
@@ -86,16 +86,19 @@ class Display final : angle::NonCopyable
     static bool isValidDisplay(const egl::Display *display);
     static bool isValidNativeDisplay(EGLNativeDisplayType display);
     static bool hasExistingWindowSurface(EGLNativeWindowType window);
 
     bool isDeviceLost() const;
     bool testDeviceLost();
     void notifyDeviceLost();
 
+    Error waitClient() const;
+    Error waitNative(EGLint engine, egl::Surface *drawSurface, egl::Surface *readSurface) const;
+
     const Caps &getCaps() const;
 
     const DisplayExtensions &getExtensions() const;
     const std::string &getExtensionString() const;
     const std::string &getVendorString() const;
 
     const AttributeMap &getAttributeMap() const { return mAttributeMap; }
     EGLNativeDisplayType getNativeDisplayId() const { return mDisplayId; }
--- a/gfx/angle/src/libANGLE/Error.cpp
+++ b/gfx/angle/src/libANGLE/Error.cpp
@@ -11,91 +11,92 @@
 
 #include "common/angleutils.h"
 
 #include <cstdarg>
 
 namespace gl
 {
 
-Error::Error(GLenum errorCode, const char *msg, ...)
-    : mCode(errorCode),
-      mMessage(nullptr)
+Error::Error(GLenum errorCode, const char *msg, ...) : mCode(errorCode), mID(errorCode)
+{
+    va_list vararg;
+    va_start(vararg, msg);
+    createMessageString();
+    *mMessage = FormatString(msg, vararg);
+    va_end(vararg);
+}
+
+Error::Error(GLenum errorCode, GLuint id, const char *msg, ...) : mCode(errorCode), mID(id)
 {
     va_list vararg;
     va_start(vararg, msg);
     createMessageString();
     *mMessage = FormatString(msg, vararg);
     va_end(vararg);
 }
 
 void Error::createMessageString() const
 {
-    if (mMessage == nullptr)
+    if (!mMessage)
     {
-        mMessage = new std::string();
+        mMessage.reset(new std::string);
     }
 }
 
 const std::string &Error::getMessage() const
 {
     createMessageString();
     return *mMessage;
 }
 
 bool Error::operator==(const Error &other) const
 {
     if (mCode != other.mCode)
         return false;
 
     // TODO(jmadill): Compare extended error codes instead of strings.
-    if ((mMessage == nullptr || other.mMessage == nullptr) &&
-        ((mMessage == nullptr) != (other.mMessage == nullptr)))
+    if ((!mMessage || !other.mMessage) && (!mMessage != !other.mMessage))
         return false;
 
     return (*mMessage == *other.mMessage);
 }
 
 bool Error::operator!=(const Error &other) const
 {
     return !(*this == other);
 }
 }
 
 namespace egl
 {
 
-Error::Error(EGLint errorCode, const char *msg, ...)
-    : mCode(errorCode),
-      mID(0),
-      mMessage(nullptr)
+Error::Error(EGLint errorCode, const char *msg, ...) : mCode(errorCode), mID(0)
 {
     va_list vararg;
     va_start(vararg, msg);
     createMessageString();
     *mMessage = FormatString(msg, vararg);
     va_end(vararg);
 }
 
-Error::Error(EGLint errorCode, EGLint id, const char *msg, ...)
-    : mCode(errorCode),
-      mID(id),
-      mMessage(nullptr)
+Error::Error(EGLint errorCode, EGLint id, const char *msg, ...) : mCode(errorCode), mID(id)
 {
     va_list vararg;
     va_start(vararg, msg);
     createMessageString();
     *mMessage = FormatString(msg, vararg);
     va_end(vararg);
 }
+
 void Error::createMessageString() const
 {
-    if (mMessage == nullptr)
+    if (!mMessage)
     {
-        mMessage = new std::string();
+        mMessage.reset(new std::string);
     }
 }
 
 const std::string &Error::getMessage() const
 {
     createMessageString();
     return *mMessage;
 }
--- a/gfx/angle/src/libANGLE/Error.h
+++ b/gfx/angle/src/libANGLE/Error.h
@@ -8,79 +8,95 @@
 
 #ifndef LIBANGLE_ERROR_H_
 #define LIBANGLE_ERROR_H_
 
 #include "angle_gl.h"
 #include <EGL/egl.h>
 
 #include <string>
+#include <memory>
 
 namespace gl
 {
 
 class Error final
 {
   public:
     explicit inline Error(GLenum errorCode);
     Error(GLenum errorCode, const char *msg, ...);
+    Error(GLenum errorCode, GLuint id, const char *msg, ...);
     inline Error(const Error &other);
     inline Error(Error &&other);
 
-    inline ~Error();
-
     inline Error &operator=(const Error &other);
     inline Error &operator=(Error &&other);
 
     inline GLenum getCode() const;
+    inline GLuint getID() const;
     inline bool isError() const;
 
     const std::string &getMessage() const;
 
     // Useful for mocking and testing
     bool operator==(const Error &other) const;
     bool operator!=(const Error &other) const;
 
   private:
     void createMessageString() const;
 
     GLenum mCode;
-    mutable std::string *mMessage;
+    GLuint mID;
+    mutable std::unique_ptr<std::string> mMessage;
 };
 
-}
+template <typename T>
+class ErrorOrResult
+{
+  public:
+    ErrorOrResult(const gl::Error &error) : mError(error) {}
+    ErrorOrResult(T &&result) : mError(GL_NO_ERROR), mResult(std::move(result)) {}
+
+    bool isError() const { return mError.isError(); }
+    const gl::Error &getError() const { return mError; }
+    T &&getResult() { return std::move(mResult); }
+
+  private:
+    Error mError;
+    T mResult;
+};
+
+}  // namespace gl
 
 namespace egl
 {
 
 class Error final
 {
   public:
     explicit inline Error(EGLint errorCode);
     Error(EGLint errorCode, const char *msg, ...);
     Error(EGLint errorCode, EGLint id, const char *msg, ...);
     inline Error(const Error &other);
     inline Error(Error &&other);
 
-    inline ~Error();
-
     inline Error &operator=(const Error &other);
     inline Error &operator=(Error &&other);
 
     inline EGLint getCode() const;
     inline EGLint getID() const;
     inline bool isError() const;
 
     const std::string &getMessage() const;
 
   private:
     void createMessageString() const;
 
     EGLint mCode;
     EGLint mID;
-    mutable std::string *mMessage;
+    mutable std::unique_ptr<std::string> mMessage;
 };
 
-}
+}  // namespace egl
 
 #include "Error.inl"
 
 #endif // LIBANGLE_ERROR_H_
--- a/gfx/angle/src/libANGLE/Error.inl
+++ b/gfx/angle/src/libANGLE/Error.inl
@@ -10,142 +10,138 @@
 
 #include <cstdarg>
 
 namespace gl
 {
 
 Error::Error(GLenum errorCode)
     : mCode(errorCode),
-      mMessage(nullptr)
+      mID(errorCode)
 {
 }
 
 Error::Error(const Error &other)
     : mCode(other.mCode),
-      mMessage(nullptr)
+      mID(other.mID)
 {
-    if (other.mMessage != nullptr)
+    if (other.mMessage)
     {
         createMessageString();
         *mMessage = *(other.mMessage);
     }
 }
 
 Error::Error(Error &&other)
     : mCode(other.mCode),
-      mMessage(other.mMessage)
+      mID(other.mID),
+      mMessage(std::move(other.mMessage))
 {
-    other.mMessage = nullptr;
-}
-
-Error::~Error()
-{
-    SafeDelete(mMessage);
 }
 
 Error &Error::operator=(const Error &other)
 {
     mCode = other.mCode;
+    mID = other.mID;
 
-    if (other.mMessage != nullptr)
+    if (other.mMessage)
     {
         createMessageString();
         *mMessage = *(other.mMessage);
     }
     else
     {
-        SafeDelete(mMessage);
+        mMessage.release();
     }
 
     return *this;
 }
 
 Error &Error::operator=(Error &&other)
 {
-    mCode = other.mCode;
-    mMessage = other.mMessage;
-
-    other.mMessage = nullptr;
+    if (this != &other)
+    {
+        mCode = other.mCode;
+        mID = other.mID;
+        mMessage = std::move(other.mMessage);
+    }
 
     return *this;
 }
 
 GLenum Error::getCode() const
 {
     return mCode;
 }
 
+GLuint Error::getID() const
+{
+    return mID;
+}
+
 bool Error::isError() const
 {
     return (mCode != GL_NO_ERROR);
 }
 
 }
 
 namespace egl
 {
 
 Error::Error(EGLint errorCode)
     : mCode(errorCode),
-      mID(0),
-      mMessage(nullptr)
+      mID(0)
 {
 }
 
 Error::Error(const Error &other)
     : mCode(other.mCode),
-      mID(other.mID),
-      mMessage(nullptr)
+      mID(other.mID)
 {
-    if (other.mMessage != nullptr)
+    if (other.mMessage)
     {
         createMessageString();
         *mMessage = *(other.mMessage);
     }
 }
 
 Error::Error(Error &&other)
     : mCode(other.mCode),
       mID(other.mID),
-      mMessage(other.mMessage)
+      mMessage(std::move(other.mMessage))
 {
-    other.mMessage = nullptr;
-}
-
-Error::~Error()
-{
-    SafeDelete(mMessage);
 }
 
 Error &Error::operator=(const Error &other)
 {
     mCode = other.mCode;
     mID = other.mID;
 
-    if (other.mMessage != nullptr)
+    if (other.mMessage)
     {
         createMessageString();
         *mMessage = *(other.mMessage);
     }
     else
     {
-        SafeDelete(mMessage);
+        mMessage.release();
     }
 
     return *this;
 }
 
 Error &Error::operator=(Error &&other)
 {
-    mCode = other.mCode;
-    mID = other.mID;
-    mMessage = other.mMessage;
-
-    other.mMessage = nullptr;
+    if (this != &other)
+    {
+        mCode = other.mCode;
+        mID = other.mID;
+        mMessage = std::move(other.mMessage);
+    }
 
     return *this;
 }
 
 EGLint Error::getCode() const
 {
     return mCode;
 }
--- a/gfx/angle/src/libANGLE/Fence.cpp
+++ b/gfx/angle/src/libANGLE/Fence.cpp
@@ -71,28 +71,35 @@ Error FenceNV::finish()
     }
 
     mStatus = GL_TRUE;
 
     return Error(GL_NO_ERROR);
 }
 
 FenceSync::FenceSync(rx::FenceSyncImpl *impl, GLuint id)
-    : RefCountObject(id),
-      mFence(impl),
-      mCondition(GL_NONE),
-      mFlags(0)
+    : RefCountObject(id), mFence(impl), mLabel(), mCondition(GL_NONE), mFlags(0)
 {
 }
 
 FenceSync::~FenceSync()
 {
     SafeDelete(mFence);
 }
 
+void FenceSync::setLabel(const std::string &label)
+{
+    mLabel = label;
+}
+
+const std::string &FenceSync::getLabel() const
+{
+    return mLabel;
+}
+
 Error FenceSync::set(GLenum condition, GLbitfield flags)
 {
     Error error = mFence->set(condition, flags);
     if (error.isError())
     {
         return error;
     }
 
--- a/gfx/angle/src/libANGLE/Fence.h
+++ b/gfx/angle/src/libANGLE/Fence.h
@@ -5,16 +5,17 @@
 //
 
 // Fence.h: Defines the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence
 // extension and GLES3 sync objects.
 
 #ifndef LIBANGLE_FENCE_H_
 #define LIBANGLE_FENCE_H_
 
+#include "libANGLE/Debug.h"
 #include "libANGLE/Error.h"
 #include "libANGLE/RefCountObject.h"
 
 #include "common/angleutils.h"
 
 namespace rx
 {
 class FenceNVImpl;
@@ -42,32 +43,37 @@ class FenceNV final : angle::NonCopyable
     rx::FenceNVImpl *mFence;
 
     bool mIsSet;
 
     GLboolean mStatus;
     GLenum mCondition;
 };
 
-class FenceSync final : public RefCountObject
+class FenceSync final : public RefCountObject, public LabeledObject
 {
   public:
-    explicit FenceSync(rx::FenceSyncImpl *impl, GLuint id);
+    FenceSync(rx::FenceSyncImpl *impl, GLuint id);
     virtual ~FenceSync();
 
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
     Error set(GLenum condition, GLbitfield flags);
     Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult);
     Error serverWait(GLbitfield flags, GLuint64 timeout);
     Error getStatus(GLint *outResult) const;
 
     GLenum getCondition() const { return mCondition; }
     GLbitfield getFlags() const { return mFlags; }
 
   private:
     rx::FenceSyncImpl *mFence;
 
+    std::string mLabel;
+
     GLenum mCondition;
     GLbitfield mFlags;
 };
 
 }
 
 #endif   // LIBANGLE_FENCE_H_
--- a/gfx/angle/src/libANGLE/Framebuffer.cpp
+++ b/gfx/angle/src/libANGLE/Framebuffer.cpp
@@ -35,35 +35,43 @@ void DetachMatchingAttachment(Framebuffe
         attachment->id() == matchId)
     {
         attachment->detach();
     }
 }
 }
 
 Framebuffer::Data::Data()
-    : mColorAttachments(1),
+    : mLabel(),
+      mColorAttachments(1),
       mDrawBufferStates(1, GL_NONE),
       mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
 {
     mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
 }
 
 Framebuffer::Data::Data(const Caps &caps)
-    : mColorAttachments(caps.maxColorAttachments),
+    : mLabel(),
+      mColorAttachments(caps.maxColorAttachments),
       mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
       mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
 {
+    ASSERT(mDrawBufferStates.size() > 0);
     mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
 }
 
 Framebuffer::Data::~Data()
 {
 }
 
+const std::string &Framebuffer::Data::getLabel()
+{
+    return mLabel;
+}
+
 const FramebufferAttachment *Framebuffer::Data::getReadAttachment() const
 {
     ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
     size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
     ASSERT(readIndex < mColorAttachments.size());
     return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
 }
 
@@ -174,16 +182,26 @@ Framebuffer::Framebuffer(rx::SurfaceImpl
     ASSERT(mImpl != nullptr);
 }
 
 Framebuffer::~Framebuffer()
 {
     SafeDelete(mImpl);
 }
 
+void Framebuffer::setLabel(const std::string &label)
+{
+    mData.mLabel = label;
+}
+
+const std::string &Framebuffer::getLabel() const
+{
+    return mData.mLabel;
+}
+
 void Framebuffer::detachTexture(GLuint textureId)
 {
     detachResourceById(GL_TEXTURE, textureId);
 }
 
 void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
 {
     detachResourceById(GL_RENDERBUFFER, renderbufferId);
@@ -265,64 +283,79 @@ const FramebufferAttachment *Framebuffer
             return getDepthStencilBuffer();
           default:
             UNREACHABLE();
             return nullptr;
         }
     }
 }
 
-GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
+size_t Framebuffer::getDrawbufferStateCount() const
 {
-    ASSERT(colorAttachment < mData.mDrawBufferStates.size());
-    return mData.mDrawBufferStates[colorAttachment];
+    return mData.mDrawBufferStates.size();
+}
+
+GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
+{
+    ASSERT(drawBuffer < mData.mDrawBufferStates.size());
+    return mData.mDrawBufferStates[drawBuffer];
 }
 
 void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
 {
     auto &drawStates = mData.mDrawBufferStates;
 
     ASSERT(count <= drawStates.size());
     std::copy(buffers, buffers + count, drawStates.begin());
     std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
-    mImpl->setDrawBuffers(count, buffers);
+    mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
+}
+
+const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
+{
+    ASSERT(drawBuffer < mData.mDrawBufferStates.size());
+    if (mData.mDrawBufferStates[drawBuffer] != GL_NONE)
+    {
+        // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
+        // must be COLOR_ATTACHMENTi or NONE"
+        ASSERT(mData.mDrawBufferStates[drawBuffer] == GL_COLOR_ATTACHMENT0 + drawBuffer ||
+               (drawBuffer == 0 && mData.mDrawBufferStates[drawBuffer] == GL_BACK));
+        return getAttachment(mData.mDrawBufferStates[drawBuffer]);
+    }
+    else
+    {
+        return nullptr;
+    }
+}
+
+bool Framebuffer::hasEnabledDrawBuffer() const
+{
+    for (size_t drawbufferIdx = 0; drawbufferIdx < mData.mDrawBufferStates.size(); ++drawbufferIdx)
+    {
+        if (getDrawBuffer(drawbufferIdx) != nullptr)
+        {
+            return true;
+        }
+    }
+
+    return false;
 }
 
 GLenum Framebuffer::getReadBufferState() const
 {
     return mData.mReadBufferState;
 }
 
 void Framebuffer::setReadBuffer(GLenum buffer)
 {
     ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
            (buffer >= GL_COLOR_ATTACHMENT0 &&
             (buffer - GL_COLOR_ATTACHMENT0) < mData.mColorAttachments.size()));
     mData.mReadBufferState = buffer;
-    mImpl->setReadBuffer(buffer);
-}
-
-bool Framebuffer::isEnabledColorAttachment(size_t colorAttachment) const
-{
-    ASSERT(colorAttachment < mData.mColorAttachments.size());
-    return (mData.mColorAttachments[colorAttachment].isAttached() &&
-            mData.mDrawBufferStates[colorAttachment] != GL_NONE);
-}
-
-bool Framebuffer::hasEnabledColorAttachment() const
-{
-    for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment)
-    {
-        if (isEnabledColorAttachment(static_cast<unsigned int>(colorAttachment)))
-        {
-            return true;
-        }
-    }
-
-    return false;
+    mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
 }
 
 size_t Framebuffer::getNumColorBuffers() const
 {
     return mData.mColorAttachments.size();
 }
 
 bool Framebuffer::hasDepth() const
@@ -332,19 +365,19 @@ bool Framebuffer::hasDepth() const
 
 bool Framebuffer::hasStencil() const
 {
     return (mData.mStencilAttachment.isAttached() && mData.mStencilAttachment.getStencilSize() > 0);
 }
 
 bool Framebuffer::usingExtendedDrawBuffers() const
 {
-    for (size_t colorAttachment = 1; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment)
+    for (size_t drawbufferIdx = 1; drawbufferIdx < mData.mDrawBufferStates.size(); ++drawbufferIdx)
     {
-        if (isEnabledColorAttachment(static_cast<unsigned int>(colorAttachment)))
+        if (getDrawBuffer(drawbufferIdx) != nullptr)
         {
             return true;
         }
     }
 
     return false;
 }
 
@@ -385,16 +418,27 @@ GLenum Framebuffer::checkStatus(const gl
                 {
                     return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
                 }
 
                 if (colorAttachment.layer() >= size.depth)
                 {
                     return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
                 }
+
+                // ES3 specifies that cube map texture attachments must be cube complete.
+                // This language is missing from the ES2 spec, but we enforce it here because some
+                // desktop OpenGL drivers also enforce this validation.
+                // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
+                const Texture *texture = colorAttachment.getTexture();
+                ASSERT(texture);
+                if (texture->getTarget() == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete())
+                {
+                    return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+                }
             }
             else if (colorAttachment.type() == GL_RENDERBUFFER)
             {
                 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
                 {
                     return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
                 }
             }
@@ -534,16 +578,17 @@ GLenum Framebuffer::checkStatus(const gl
 
     // In ES 2.0, all color attachments must have the same width and height.
     // In ES 3.0, there is no such restriction.
     if (data.clientVersion < 3 && !mData.attachmentsHaveSameDimensions())
     {
         return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
     }
 
+    syncState();
     if (!mImpl->checkStatus())
     {
         return GL_FRAMEBUFFER_UNSUPPORTED;
     }
 
     return GL_FRAMEBUFFER_COMPLETE;
 }
 
@@ -557,140 +602,117 @@ Error Framebuffer::invalidate(size_t cou
     return mImpl->invalidate(count, attachments);
 }
 
 Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
 {
     return mImpl->invalidateSub(count, attachments, area);
 }
 
-Error Framebuffer::clear(Context *context, GLbitfield mask)
+Error Framebuffer::clear(const gl::Data &data, GLbitfield mask)
 {
-    if (context->getState().isRasterizerDiscardEnabled())
+    if (data.state->isRasterizerDiscardEnabled())
     {
         return gl::Error(GL_NO_ERROR);
     }
 
-    // Sync the clear state
-    context->syncRendererState(context->getState().clearStateBitMask());
-
-    return mImpl->clear(context->getData(), mask);
+    return mImpl->clear(data, mask);
 }
 
-Error Framebuffer::clearBufferfv(Context *context,
+Error Framebuffer::clearBufferfv(const gl::Data &data,
                                  GLenum buffer,
                                  GLint drawbuffer,
                                  const GLfloat *values)
 {
-    if (context->getState().isRasterizerDiscardEnabled())
+    if (data.state->isRasterizerDiscardEnabled())
     {
         return gl::Error(GL_NO_ERROR);
     }
 
-    // Sync the clear state
-    context->syncRendererState(context->getState().clearStateBitMask());
-    return mImpl->clearBufferfv(context->getData(), buffer, drawbuffer, values);
+    return mImpl->clearBufferfv(data, buffer, drawbuffer, values);
 }
 
-Error Framebuffer::clearBufferuiv(Context *context,
+Error Framebuffer::clearBufferuiv(const gl::Data &data,
                                   GLenum buffer,
                                   GLint drawbuffer,
                                   const GLuint *values)
 {
-    if (context->getState().isRasterizerDiscardEnabled())
+    if (data.state->isRasterizerDiscardEnabled())
     {
         return gl::Error(GL_NO_ERROR);
     }
 
-    // Sync the clear state
-    context->syncRendererState(context->getState().clearStateBitMask());
-
-    return mImpl->clearBufferuiv(context->getData(), buffer, drawbuffer, values);
+    return mImpl->clearBufferuiv(data, buffer, drawbuffer, values);
 }
 
-Error Framebuffer::clearBufferiv(Context *context,
+Error Framebuffer::clearBufferiv(const gl::Data &data,
                                  GLenum buffer,
                                  GLint drawbuffer,
                                  const GLint *values)
 {
-    if (context->getState().isRasterizerDiscardEnabled())
+    if (data.state->isRasterizerDiscardEnabled())
     {
         return gl::Error(GL_NO_ERROR);
     }
 
-    // Sync the clear state
-    context->syncRendererState(context->getState().clearStateBitMask());
-
-    return mImpl->clearBufferiv(context->getData(), buffer, drawbuffer, values);
+    return mImpl->clearBufferiv(data, buffer, drawbuffer, values);
 }
 
-Error Framebuffer::clearBufferfi(Context *context,
+Error Framebuffer::clearBufferfi(const gl::Data &data,
                                  GLenum buffer,
                                  GLint drawbuffer,
                                  GLfloat depth,
                                  GLint stencil)
 {
-    if (context->getState().isRasterizerDiscardEnabled())
+    if (data.state->isRasterizerDiscardEnabled())
     {
         return gl::Error(GL_NO_ERROR);
     }
 
-    // Sync the clear state
-    context->syncRendererState(context->getState().clearStateBitMask());
-
-    return mImpl->clearBufferfi(context->getData(), buffer, drawbuffer, depth, stencil);
+    return mImpl->clearBufferfi(data, buffer, drawbuffer, depth, stencil);
 }
 
 GLenum Framebuffer::getImplementationColorReadFormat() const
 {
     return mImpl->getImplementationColorReadFormat();
 }
 
 GLenum Framebuffer::getImplementationColorReadType() const
 {
     return mImpl->getImplementationColorReadType();
 }
 
-Error Framebuffer::readPixels(Context *context,
-                              const gl::Rectangle &area,
+Error Framebuffer::readPixels(const State &state,
+                              const Rectangle &area,
                               GLenum format,
                               GLenum type,
                               GLvoid *pixels) const
 {
-    const State &state = context->getState();
-
-    // Sync pack state
-    context->syncRendererState(state.packStateBitMask());
-
     Error error = mImpl->readPixels(state, area, format, type, pixels);
     if (error.isError())
     {
         return error;
     }
 
     Buffer *unpackBuffer = state.getUnpackState().pixelBuffer.get();
     if (unpackBuffer)
     {
         unpackBuffer->onPixelUnpack();
     }
 
     return Error(GL_NO_ERROR);
 }
 
-Error Framebuffer::blit(Context *context,
-                        const gl::Rectangle &sourceArea,
-                        const gl::Rectangle &destArea,
+Error Framebuffer::blit(const State &state,
+                        const Rectangle &sourceArea,
+                        const Rectangle &destArea,
                         GLbitfield mask,
                         GLenum filter,
-                        const gl::Framebuffer *sourceFramebuffer)
+                        const Framebuffer *sourceFramebuffer)
 {
-    // Sync blit state
-    const State &state = context->getState();
-    context->syncRendererState(state.blitStateBitMask());
-
     return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer);
 }
 
 int Framebuffer::getSamples(const gl::Data &data) const
 {
     if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
     {
         // for a complete framebuffer, all attachments must have the same sample count
@@ -730,46 +752,56 @@ void Framebuffer::setAttachment(GLenum t
             {
                 // Attaching nullptr detaches the current attachment.
                 attachmentObj = nullptr;
             }
         }
 
         mData.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
         mData.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
-        mImpl->onUpdateDepthStencilAttachment();
+        mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
+        mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
     }
     else
     {
         switch (binding)
         {
-          case GL_DEPTH:
-          case GL_DEPTH_ATTACHMENT:
-            mData.mDepthAttachment.attach(type, binding, textureIndex, resource);
-            mImpl->onUpdateDepthAttachment();
+            case GL_DEPTH:
+            case GL_DEPTH_ATTACHMENT:
+                mData.mDepthAttachment.attach(type, binding, textureIndex, resource);
+                mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
             break;
-          case GL_STENCIL:
-          case GL_STENCIL_ATTACHMENT:
-            mData.mStencilAttachment.attach(type, binding, textureIndex, resource);
-            mImpl->onUpdateStencilAttachment();
+            case GL_STENCIL:
+            case GL_STENCIL_ATTACHMENT:
+                mData.mStencilAttachment.attach(type, binding, textureIndex, resource);
+                mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
             break;
-          case GL_BACK:
-            mData.mColorAttachments[0].attach(type, binding, textureIndex, resource);
-            mImpl->onUpdateColorAttachment(0);
+            case GL_BACK:
+                mData.mColorAttachments[0].attach(type, binding, textureIndex, resource);
+                mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
             break;
-          default:
+            default:
             {
                 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
                 ASSERT(colorIndex < mData.mColorAttachments.size());
                 mData.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
-                mImpl->onUpdateColorAttachment(colorIndex);
+                mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
             }
             break;
         }
     }
 }
 
 void Framebuffer::resetAttachment(GLenum binding)
 {
     setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
 }
 
+void Framebuffer::syncState() const
+{
+    if (mDirtyBits.any())
+    {
+        mImpl->syncState(mDirtyBits);
+        mDirtyBits.reset();
+    }
 }
+
+}  // namespace gl
--- a/gfx/angle/src/libANGLE/Framebuffer.h
+++ b/gfx/angle/src/libANGLE/Framebuffer.h
@@ -9,16 +9,17 @@
 
 #ifndef LIBANGLE_FRAMEBUFFER_H_
 #define LIBANGLE_FRAMEBUFFER_H_
 
 #include <vector>
 
 #include "common/angleutils.h"
 #include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
 #include "libANGLE/Error.h"
 #include "libANGLE/FramebufferAttachment.h"
 #include "libANGLE/RefCountObject.h"
 
 namespace rx
 {
 class ImplFactory;
 class FramebufferImpl;
@@ -39,55 +40,63 @@ class State;
 class Texture;
 class TextureCapsMap;
 struct Caps;
 struct Data;
 struct Extensions;
 struct ImageIndex;
 struct Rectangle;
 
-class Framebuffer
+class Framebuffer final : public LabeledObject
 {
   public:
 
     class Data final : angle::NonCopyable
     {
       public:
         explicit Data();
         explicit Data(const Caps &caps);
         ~Data();
 
+        const std::string &getLabel();
+
         const FramebufferAttachment *getReadAttachment() const;
         const FramebufferAttachment *getFirstColorAttachment() const;
         const FramebufferAttachment *getDepthOrStencilAttachment() const;
         const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
         const FramebufferAttachment *getDepthAttachment() const;
         const FramebufferAttachment *getStencilAttachment() const;
         const FramebufferAttachment *getDepthStencilAttachment() const;
 
         const std::vector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; }
+        GLenum getReadBufferState() const { return mReadBufferState; }
         const std::vector<FramebufferAttachment> &getColorAttachments() const { return mColorAttachments; }
 
         bool attachmentsHaveSameDimensions() const;
 
       private:
         friend class Framebuffer;
 
+        std::string mLabel;
+
         std::vector<FramebufferAttachment> mColorAttachments;
         FramebufferAttachment mDepthAttachment;
         FramebufferAttachment mStencilAttachment;
 
         std::vector<GLenum> mDrawBufferStates;
         GLenum mReadBufferState;
     };
 
     Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id);
     Framebuffer(rx::SurfaceImpl *surface);
     virtual ~Framebuffer();
 
+    void setLabel(const std::string &label) override;
+    const std::string &getLabel() const override;
+
     const rx::FramebufferImpl *getImplementation() const { return mImpl; }
     rx::FramebufferImpl *getImplementation() { return mImpl; }
 
     GLuint id() const { return mId; }
 
     void setAttachment(GLenum type,
                        GLenum binding,
                        const ImageIndex &textureIndex,
@@ -103,65 +112,93 @@ class Framebuffer
     const FramebufferAttachment *getDepthStencilBuffer() const;
     const FramebufferAttachment *getDepthOrStencilbuffer() const;
     const FramebufferAttachment *getReadColorbuffer() const;
     GLenum getReadColorbufferType() const;
     const FramebufferAttachment *getFirstColorbuffer() const;
 
     const FramebufferAttachment *getAttachment(GLenum attachment) const;
 
-    GLenum getDrawBufferState(unsigned int colorAttachment) const;
+    size_t getDrawbufferStateCount() const;
+    GLenum getDrawBufferState(size_t drawBuffer) const;
     void setDrawBuffers(size_t count, const GLenum *buffers);
+    const FramebufferAttachment *getDrawBuffer(size_t drawBuffer) const;
+    bool hasEnabledDrawBuffer() const;
 
     GLenum getReadBufferState() const;
     void setReadBuffer(GLenum buffer);
 
-    bool isEnabledColorAttachment(size_t colorAttachment) const;
-    bool hasEnabledColorAttachment() const;
     size_t getNumColorBuffers() const;
     bool hasDepth() const;
     bool hasStencil() const;
     int getSamples(const gl::Data &data) const;
     bool usingExtendedDrawBuffers() const;
 
     GLenum checkStatus(const gl::Data &data) const;
     bool hasValidDepthStencil() const;
 
     Error discard(size_t count, const GLenum *attachments);
     Error invalidate(size_t count, const GLenum *attachments);
     Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area);
 
-    Error clear(Context *context, GLbitfield mask);
-    Error clearBufferfv(Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *values);
-    Error clearBufferuiv(Context *context, GLenum buffer, GLint drawbuffer, const GLuint *values);
-    Error clearBufferiv(Context *context, GLenum buffer, GLint drawbuffer, const GLint *values);
-    Error clearBufferfi(Context *context,
+    Error clear(const gl::Data &data, GLbitfield mask);
+    Error clearBufferfv(const gl::Data &data,
+                        GLenum buffer,
+                        GLint drawbuffer,
+                        const GLfloat *values);
+    Error clearBufferuiv(const gl::Data &data,
+                         GLenum buffer,
+                         GLint drawbuffer,
+                         const GLuint *values);
+    Error clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values);
+    Error clearBufferfi(const gl::Data &data,
                         GLenum buffer,
                         GLint drawbuffer,
                         GLfloat depth,
                         GLint stencil);
 
     GLenum getImplementationColorReadFormat() const;
     GLenum getImplementationColorReadType() const;
-    Error readPixels(Context *context,
+    Error readPixels(const gl::State &state,
                      const gl::Rectangle &area,
                      GLenum format,
                      GLenum type,
                      GLvoid *pixels) const;
 
-    Error blit(Context *context,
-               const gl::Rectangle &sourceArea,
-               const gl::Rectangle &destArea,
+    Error blit(const State &state,
+               const Rectangle &sourceArea,
+               const Rectangle &destArea,
                GLbitfield mask,
                GLenum filter,
-               const gl::Framebuffer *sourceFramebuffer);
+               const Framebuffer *sourceFramebuffer);
+
+    enum DirtyBitType
+    {
+        DIRTY_BIT_COLOR_ATTACHMENT_0,
+        DIRTY_BIT_COLOR_ATTACHMENT_MAX =
+            DIRTY_BIT_COLOR_ATTACHMENT_0 + gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS,
+        DIRTY_BIT_DEPTH_ATTACHMENT = DIRTY_BIT_COLOR_ATTACHMENT_MAX,
+        DIRTY_BIT_STENCIL_ATTACHMENT,
+        DIRTY_BIT_DRAW_BUFFERS,
+        DIRTY_BIT_READ_BUFFER,
+        DIRTY_BIT_UNKNOWN,
+        DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN,
+    };
+
+    typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
+    bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
+    void syncState() const;
 
   protected:
     void detachResourceById(GLenum resourceType, GLuint resourceId);
 
     Data mData;
     rx::FramebufferImpl *mImpl;
     GLuint mId;
+
+    // TODO(jmadill): See if we can make this non-mutable.
+    mutable DirtyBits mDirtyBits;
 };
 
 }
 
 #endif   // LIBANGLE_FRAMEBUFFER_H_
--- a/gfx/angle/src/libANGLE/HandleAllocator.cpp
+++ b/gfx/angle/src/libANGLE/HandleAllocator.cpp
@@ -121,13 +121,14 @@ void HandleAllocator::reserve(GLuint han
     auto placementIt = mUnallocatedList.erase(boundIt);
 
     if (handle + 1 != end)
     {
         placementIt = mUnallocatedList.insert(placementIt, HandleRange(handle + 1, end));
     }
     if (begin != handle)
     {
+        ASSERT(begin < handle);
         mUnallocatedList.insert(placementIt, HandleRange(begin, handle));
     }
 }
 
-}
+}  // namespace gl
--- a/gfx/angle/src/libANGLE/HandleAllocator.h
+++ b/gfx/angle/src/libANGLE/HandleAllocator.h
@@ -53,11 +53,11 @@ class HandleAllocator final : angle::Non
 
     // The freelist consists of never-allocated handles, stored
     // as ranges, and handles that were previously allocated and
     // released, stored in a stack.
     std::vector<HandleRange> mUnallocatedList;
     std::vector<GLuint> mReleasedList;
 };
 
-}
+}  // namespace gl
 
 #endif   // LIBANGLE_HANDLEALLOCATOR_H_
--- a/gfx/angle/src/libANGLE/Program.cpp
+++ b/gfx/angle/src/libANGLE/Program.cpp
@@ -218,17 +218,18 @@ VariableLocation::VariableLocation()
 VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
     : name(name),
       element(element),
       index(index)
 {
 }
 
 Program::Data::Data()
-    : mAttachedFragmentShader(nullptr),
+    : mLabel(),
+      mAttachedFragmentShader(nullptr),
       mAttachedVertexShader(null