Merge inbound to m-c a=merge
authorWes Kocher <wkocher@mozilla.com>
Thu, 09 Oct 2014 21:24:56 -0700
changeset 232932 50b689feab5f519b102141d629137cfd40bcd60b
parent 232919 b91b22431613232f0818721e064002575a04ff9f (current diff)
parent 232931 1da6afd3818adfb57ad92157add1324453efdf08 (diff)
child 232935 6d25927a7532e0f830183ce1ba13234822e300e2
child 232948 f09199bad1200ffee2ad5b73b7c15eb1aec815a7
child 232959 c1617b7400c0caeb7d05acfff5a843b90ec27a1b
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone35.0a1
first release with
nightly linux32
50b689feab5f / 35.0a1 / 20141010030201 / files
nightly linux64
50b689feab5f / 35.0a1 / 20141010030201 / files
nightly mac
50b689feab5f / 35.0a1 / 20141010030201 / files
nightly win32
50b689feab5f / 35.0a1 / 20141010030201 / files
nightly win64
50b689feab5f / 35.0a1 / 20141010030201 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c a=merge
--- a/dom/tests/mochitest/general/mochitest.ini
+++ b/dom/tests/mochitest/general/mochitest.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+skip-if = e10s
 support-files =
   497633.html
   file_MozEnteredDomFullscreen.html
   file_bug628069.html
   file_clonewrapper.html
   file_domWindowUtils_scrollbarSize.html
   file_frameElementWrapping.html
   file_interfaces.xml
@@ -29,62 +30,62 @@ support-files =
   res6.resource^headers^
   res7.resource
   res7.resource^headers^
   res8.resource
   res8.resource^headers^
   resource_timing.js
 
 [test_497898.html]
-skip-if = ((buildapp == 'mulet' || buildapp == 'b2g') && toolkit != 'gonk') || toolkit == 'android' #Bug 931116, b2g desktop specific, initial triage
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' #Bug 931116, b2g desktop specific, initial triage
 [test_bug504220.html]
 [test_bug628069_1.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug628069_2.html]
 [test_bug631440.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug653364.html]
 [test_bug861217.html]
 [test_clientRects.html]
 [test_clipboard_events.html]
-skip-if = e10s || buildapp == 'b2g' # b2g(clipboard undefined) b2g-debug(clipboard undefined) b2g-desktop(clipboard undefined)
+skip-if = buildapp == 'b2g' # b2g(clipboard undefined) b2g-debug(clipboard undefined) b2g-desktop(clipboard undefined)
 [test_consoleAPI.html]
 [test_DOMMatrix.html]
 [test_domWindowUtils.html]
 [test_domWindowUtils_scrollXY.html]
 [test_domWindowUtils_scrollbarSize.html]
 [test_donottrack.html]
 skip-if = buildapp == 'mulet'
 [test_focus_legend_noparent.html]
 [test_focusrings.xul]
-skip-if = e10s || buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
+skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
 [test_for_of.html]
 [test_frameElementWrapping.html]
 [test_framedhistoryframes.html]
 [test_idleapi_permissions.html]
-skip-if = e10s || buildapp == 'b2g' || buildapp == 'mulet'
+skip-if = buildapp == 'b2g' || buildapp == 'mulet'
 [test_interfaces.html]
 skip-if = ((buildapp == 'mulet' || buildapp == 'b2g') && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 # [test_network_events.html]
 # Disable this test until bug 795711 is fixed.
 [test_offsets.html]
 [test_offsets.js]
 [test_outerHTML.html]
 [test_outerHTML.xhtml]
 skip-if = buildapp == 'mulet'
 [test_paste_selection.html]
 skip-if = buildapp == 'mulet'
 [test_picture_pref.html]
 [test_resource_timing.html]
-skip-if = buildapp == 'b2g' || buildapp == 'mulet'
+skip-if = buildapp == 'b2g' || buildapp == 'mulet' # b2g(No clipboard) b2g-debug(No clipboard) b2g-desktop(No clipboard)
 [test_resource_timing_cross_origin.html]
 skip-if = buildapp == 'b2g' || buildapp == 'mulet'
 [test_performance_now.html]
 [test_srcset_pref.html]
 [test_showModalDialog.html]
-skip-if = e10s || buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #Don't run modal tests on Android # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
+skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #Don't run modal tests on Android # b2g(showmodaldialog) b2g-debug(showmodaldialog) b2g-desktop(showmodaldialog)
 [test_stylesheetPI.html]
 [test_vibrator.html]
 skip-if = buildapp == 'mulet' || toolkit == 'android' #CRASH_SUTAGENT
 [test_windowProperties.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_windowedhistoryframes.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
--- a/dom/tests/mochitest/general/test_resource_timing.html
+++ b/dom/tests/mochitest/general/test_resource_timing.html
@@ -15,24 +15,21 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 
 <pre id="test">
 <script type="application/javascript">
 
 SimpleTest.waitForExplicitFinish();
 
 // Resource timing is prefed off by default, so we had to use this workaround
-SpecialPowers.pushPrefEnv({"set": [["dom.enable_resource_timing", true]]}, start);
-var subwindow = null;
-
-function start() {
-  subwindow = window.open("resource_timing_main_test.html");
-}
+SpecialPowers.setBoolPref("dom.enable_resource_timing", true);
+var subwindow = window.open("resource_timing_main_test.html");
 
 function finishTests() {
   subwindow.close();
+  SpecialPowers.setBoolPref("dom.enable_resource_timing", false);
   SimpleTest.finish();
 }
 </script>
 </pre>
 
 </body>
 </html>
--- a/embedding/browser/nsDocShellTreeOwner.cpp
+++ b/embedding/browser/nsDocShellTreeOwner.cpp
@@ -1130,17 +1130,17 @@ NS_IMPL_ISUPPORTS(ChromeTooltipListener,
 // ChromeTooltipListener ctor
 //
 
 ChromeTooltipListener::ChromeTooltipListener(nsWebBrowser* inBrowser,
                                              nsIWebBrowserChrome* inChrome) 
   : mWebBrowser(inBrowser), mWebBrowserChrome(inChrome),
      mTooltipListenerInstalled(false),
      mMouseClientX(0), mMouseClientY(0),
-     mShowingTooltip(false)
+     mShowingTooltip(false), mTooltipShownOnce(false)
 {
   mTooltipTextProvider = do_GetService(NS_TOOLTIPTEXTPROVIDER_CONTRACTID);
   if (!mTooltipTextProvider) {
     nsISupports *pProvider = (nsISupports *) new DefaultTooltipTextProvider;
     mTooltipTextProvider = do_QueryInterface(pProvider);
   }
 } // ctor
 
@@ -1265,21 +1265,27 @@ ChromeTooltipListener::RemoveTooltipList
 
 NS_IMETHODIMP
 ChromeTooltipListener::HandleEvent(nsIDOMEvent* aEvent)
 {
   nsAutoString eventType;
   aEvent->GetType(eventType);
 
   if (eventType.EqualsLiteral("keydown") ||
-      eventType.EqualsLiteral("mousedown") ||
-      eventType.EqualsLiteral("mouseout"))
+      eventType.EqualsLiteral("mousedown")) {
     return HideTooltip();
-  if (eventType.EqualsLiteral("mousemove"))
+  }
+  else if (eventType.EqualsLiteral("mouseout")) {
+    // Reset flag so that tooltip will display on the next MouseMove
+    mTooltipShownOnce = false;
+    return HideTooltip();
+  }
+  else if (eventType.EqualsLiteral("mousemove")) {
     return MouseMove(aEvent);
+  }
 
   NS_ERROR("Unexpected event type");
   return NS_OK;
 }
 
 //
 // MouseMove
 //
@@ -1297,45 +1303,53 @@ ChromeTooltipListener::MouseMove(nsIDOME
   // timer callback. On win32, we'll get a MouseMove event even when a popup goes away --
   // even when the mouse doesn't change position! To get around this, we make sure the
   // mouse has really moved before proceeding.
   int32_t newMouseX, newMouseY;
   mouseEvent->GetClientX(&newMouseX);
   mouseEvent->GetClientY(&newMouseY);
   if ( mMouseClientX == newMouseX && mMouseClientY == newMouseY )
     return NS_OK;
+
+  // Filter out minor mouse movements.
+  if (mShowingTooltip &&
+      (abs(mMouseClientX - newMouseX) <= kTooltipMouseMoveTolerance) &&
+      (abs(mMouseClientY - newMouseY) <= kTooltipMouseMoveTolerance))
+    return NS_OK;
+
   mMouseClientX = newMouseX; mMouseClientY = newMouseY;
   mouseEvent->GetScreenX(&mMouseScreenX);
   mouseEvent->GetScreenY(&mMouseScreenY);
 
-  // We want to close the tip if it is being displayed and the mouse moves. Recall 
-  // that |mShowingTooltip| is set when the popup is showing. Furthermore, as the mouse
-  // moves, we want to make sure we reset the timer to show it, so that the delay
-  // is from when the mouse stops moving, not when it enters the element.
-  if ( mShowingTooltip )
-    return HideTooltip();
-  if ( mTooltipTimer )
+  if ( mTooltipTimer ) {
     mTooltipTimer->Cancel();
+  }
 
-  mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1");
-  if ( mTooltipTimer ) {
-    nsCOMPtr<EventTarget> eventTarget = aMouseEvent->InternalDOMEvent()->GetTarget();
-    if ( eventTarget )
-      mPossibleTooltipNode = do_QueryInterface(eventTarget);
-    if ( mPossibleTooltipNode ) {
-      nsresult rv =
-        mTooltipTimer->InitWithFuncCallback(sTooltipCallback, this,
-          LookAndFeel::GetInt(LookAndFeel::eIntID_TooltipDelay, 500),
-          nsITimer::TYPE_ONE_SHOT);
-      if (NS_FAILED(rv))
-        mPossibleTooltipNode = nullptr;
+  if (!mShowingTooltip && !mTooltipShownOnce) {
+    mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1");
+    if ( mTooltipTimer ) {
+      nsCOMPtr<EventTarget> eventTarget = aMouseEvent->InternalDOMEvent()->GetTarget();
+      if ( eventTarget )
+        mPossibleTooltipNode = do_QueryInterface(eventTarget);
+      if ( mPossibleTooltipNode ) {
+        nsresult rv =
+          mTooltipTimer->InitWithFuncCallback(sTooltipCallback, this,
+            LookAndFeel::GetInt(LookAndFeel::eIntID_TooltipDelay, 500),
+            nsITimer::TYPE_ONE_SHOT);
+        if (NS_FAILED(rv))
+          mPossibleTooltipNode = nullptr;
+      }
     }
+    else
+      NS_WARNING ( "Could not create a timer for tooltip tracking" );
   }
-  else
-    NS_WARNING ( "Could not create a timer for tooltip tracking" );
+  else {
+    mTooltipShownOnce = true;
+    return HideTooltip();
+  }
 
   return NS_OK;
 
 } // MouseMove
 
 
 //
 // ShowTooltip
@@ -1374,20 +1388,16 @@ ChromeTooltipListener::HideTooltip()
   
   // shut down the relevant timers
   if ( mTooltipTimer ) {
     mTooltipTimer->Cancel();
     mTooltipTimer = nullptr;
     // release tooltip target
     mPossibleTooltipNode = nullptr;
   }
-  if ( mAutoHideTimer ) {
-    mAutoHideTimer->Cancel();
-    mAutoHideTimer = nullptr;
-  }
 
   // if we're showing the tip, tell the chrome to hide it
   if ( mShowingTooltip ) {
     nsCOMPtr<nsITooltipListener> tooltipListener ( do_QueryInterface(mWebBrowserChrome) );
     if ( tooltipListener ) {
       rv = tooltipListener->OnHideTooltip ( );
       if ( NS_SUCCEEDED(rv) )
         mShowingTooltip = false;
@@ -1456,72 +1466,30 @@ ChromeTooltipListener::sTooltipCallback(
     if (self->mTooltipTextProvider) {
       bool textFound = false;
 
       self->mTooltipTextProvider->GetNodeText(
           self->mPossibleTooltipNode, getter_Copies(tooltipText), &textFound);
       
       if (textFound) {
         nsString tipText(tooltipText);
-        self->CreateAutoHideTimer();
         nsIntPoint screenDot = widget->WidgetToScreenOffset();
         self->ShowTooltip (self->mMouseScreenX - screenDot.x,
                            self->mMouseScreenY - screenDot.y,
                            tipText);
       }
     }
     
     // release tooltip target if there is one, NO MATTER WHAT
     self->mPossibleTooltipNode = nullptr;
   } // if "self" data valid
   
 } // sTooltipCallback
 
 
-//
-// CreateAutoHideTimer
-//
-// Create a new timer to see if we should auto-hide. It's ok if this fails.
-//
-void
-ChromeTooltipListener::CreateAutoHideTimer()
-{
-  // just to be anal (er, safe)
-  if ( mAutoHideTimer ) {
-    mAutoHideTimer->Cancel();
-    mAutoHideTimer = nullptr;
-  }
-  
-  mAutoHideTimer = do_CreateInstance("@mozilla.org/timer;1");
-  if ( mAutoHideTimer )
-    mAutoHideTimer->InitWithFuncCallback(sAutoHideCallback, this, kTooltipAutoHideTime, 
-                                         nsITimer::TYPE_ONE_SHOT);
-
-} // CreateAutoHideTimer
-
-
-//
-// sAutoHideCallback
-//
-// This fires after a tooltip has been open for a certain length of time. Just tell
-// the listener to close the popup. We don't have to worry, because HideTooltip() can
-// be called multiple times, even if the tip has already been closed.
-//
-void
-ChromeTooltipListener::sAutoHideCallback(nsITimer *aTimer, void* aListener)
-{
-  ChromeTooltipListener* self = static_cast<ChromeTooltipListener*>(aListener);
-  if ( self )
-    self->HideTooltip();
-
-  // NOTE: |aTimer| and |self->mAutoHideTimer| are invalid after calling ClosePopup();
-  
-} // sAutoHideCallback
-
-
 NS_IMPL_ISUPPORTS(ChromeContextMenuListener, nsIDOMEventListener)
 
 
 //
 // ChromeTooltipListener ctor
 //
 ChromeContextMenuListener::ChromeContextMenuListener(nsWebBrowser* inBrowser, nsIWebBrowserChrome* inChrome ) 
   : mContextMenuListenerInstalled(false),
--- a/embedding/browser/nsDocShellTreeOwner.h
+++ b/embedding/browser/nsDocShellTreeOwner.h
@@ -161,17 +161,18 @@ public:
     // the embedding chrome implements.
   NS_IMETHOD AddChromeListeners();
   NS_IMETHOD RemoveChromeListeners();
 
 private:
 
     // various delays for tooltips
   enum {
-    kTooltipAutoHideTime = 5000        // 5000ms = 5 seconds
+    kTooltipAutoHideTime = 5000,       // 5000ms = 5 seconds
+    kTooltipMouseMoveTolerance = 7     // 7 pixel tolerance for mousemove event
   };
 
   NS_IMETHOD AddTooltipListener();
   NS_IMETHOD RemoveTooltipListener();
 
   NS_IMETHOD ShowTooltip ( int32_t inXCoords, int32_t inYCoords, const nsAString & inTipText ) ;
   NS_IMETHOD HideTooltip ( ) ;
 
@@ -187,21 +188,17 @@ private:
 
   bool mTooltipListenerInstalled;
 
   nsCOMPtr<nsITimer> mTooltipTimer;
   static void sTooltipCallback ( nsITimer* aTimer, void* aListener ) ;
   int32_t mMouseClientX, mMouseClientY;       // mouse coordinates for last mousemove event we saw
   int32_t mMouseScreenX, mMouseScreenY;       // mouse coordinates for tooltip event
   bool mShowingTooltip;
-
-    // a timer for auto-hiding the tooltip after a certain delay
-  nsCOMPtr<nsITimer> mAutoHideTimer;
-  static void sAutoHideCallback ( nsITimer* aTimer, void* aListener ) ;
-  void CreateAutoHideTimer ( ) ;
+  bool mTooltipShownOnce;
 
     // The node hovered over that fired the timer. This may turn into the node that
     // triggered the tooltip, but only if the timer ever gets around to firing.
     // This is a strong reference, because the tooltip content can be destroyed while we're
     // waiting for the tooltip to pup up, and we need to detect that.
     // It's set only when the tooltip timer is created and launched. The timer must
     // either fire or be cancelled (or possibly released?), and we release this
     // reference in each of those cases. So we don't leak.
--- a/gfx/angle/AUTHORS
+++ b/gfx/angle/AUTHORS
@@ -9,16 +9,17 @@
 
 Google Inc.
 TransGaming Inc.
 3DLabs Inc. Ltd.
 
 Adobe Systems Inc.
 Autodesk, Inc.
 BlackBerry Limited
+Borbitsoft
 Cable Television Laboratories, Inc.
 Cloud Party, Inc.
 Intel Corporation
 Mozilla Corporation
 Turbulenz
 Klarälvdalens Datakonsult AB
 Microsoft Open Technologies, Inc.
 
--- a/gfx/angle/BUILD.gn
+++ b/gfx/angle/BUILD.gn
@@ -48,20 +48,19 @@ component("translator") {
   defines = [ "ANGLE_TRANSLATOR_IMPLEMENTATION" ]
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     "//build/config/compiler:no_chromium_code",
   ]
 
-  deps = [
+  public_deps = [
     ":translator_lib",
   ]
-  forward_dependent_configs_from = [ ":translator_lib" ]
 }
 
 # Holds the shared includes so we only need to list them once.
 source_set("includes") {
   sources = [
     "include/EGL/egl.h",
     "include/EGL/eglext.h",
     "include/EGL/eglplatform.h",
@@ -94,17 +93,17 @@ static_library("translator_lib") {
   sources = rebase_path(compiler_gypi.angle_translator_lib_sources, ".", "src")
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     ":translator_static_config",
     "//build/config/compiler:no_chromium_code",
   ]
-  direct_dependent_configs = [ ":external_config" ]
+  public_configs = [ ":external_config" ]
 
   deps = [
     ":includes",
     ":preprocessor",
   ]
 }
 
 static_library("translator_static") {
@@ -113,22 +112,21 @@ static_library("translator_static") {
     "src/compiler/translator/ShaderVars.cpp",
   ]
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     ":internal_config",
     "//build/config/compiler:no_chromium_code",
   ]
-  direct_dependent_configs = [ ":translator_static_config" ]
+  public_configs = [ ":translator_static_config" ]
 
-  deps = [
+  public_deps = [
     ":translator_lib",
   ]
-  forward_dependent_configs_from = [ ":translator_lib" ]
 }
 
 config("commit_id_config") {
   include_dirs = [ "$root_gen_dir/angle" ]
 }
 
 action("commit_id") {
   script = "src/commit_id.py"
@@ -137,25 +135,30 @@ action("commit_id") {
   outputs = [ output_file ]
 
   args = [
     "gen",
     rebase_path(".", root_build_dir),
     rebase_path(output_file, root_build_dir),
   ]
 
-  direct_dependent_configs = [ ":commit_id_config" ]
+  public_configs = [ ":commit_id_config" ]
 }
 
 if (is_win) {
   angle_enable_d3d9 = true
   angle_enable_d3d11 = true
 
   shared_library("libGLESv2") {
-    sources = rebase_path(gles_gypi.angle_libglesv2_sources, ".", "src")
+    sources = rebase_path(gles_gypi.angle_libangle_sources, ".", "src")
+    sources += [
+      "src/libGLESv2/libGLESv2.cpp",
+      "src/libGLESv2/libGLESv2.def",
+      "src/libGLESv2/libGLESv2.rc",
+    ]
 
     defines = [
       "ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ " +
         "\"d3dcompiler_46.dll\", \"d3dcompiler_43.dll\" }",
       "GL_APICALL=",
       "GL_GLEXT_PROTOTYPES=",
       "EGLAPI=",
     ]
--- a/gfx/angle/CONTRIBUTORS
+++ b/gfx/angle/CONTRIBUTORS
@@ -44,16 +44,19 @@ Google Inc.
 Adobe Systems Inc.
  Alexandru Chiculita
  Steve Minns
  Max Vujovic
 
 Autodesk, Inc.
  Ranger Harke
 
+Borbitsoft
+ Tibor den Ouden
+
 Cloud Party, Inc.
  Conor Dickinson
 
 Digia Plc
  Andrew Knight
 
 Intel Corporation
  Jin Yang
@@ -73,12 +76,13 @@ Mozilla Corp.
  Vladimir Vukicevic
 
 Turbulenz
  Michael Braithwaite
 
 Ulrik Persson (ddefrostt)
 Mark Banner (standard8mbp)
 David Kilzer
+Jacek Caban
 
 Microsoft Open Technologies, Inc.
 Cooper Partin
 Austin Kinross
--- a/gfx/angle/DEPS
+++ b/gfx/angle/DEPS
@@ -1,11 +1,11 @@
 deps = {
   "third_party/gyp":
-      "http://gyp.googlecode.com/svn/trunk@1806",
+      "http://gyp.googlecode.com/svn/trunk@1987",
 
   "tests/third_party/googletest":
       "http://googletest.googlecode.com/svn/trunk@629",
 
   "tests/third_party/googlemock":
       "http://googlemock.googlecode.com/svn/trunk@410",
 }
 
--- a/gfx/angle/moz.build
+++ b/gfx/angle/moz.build
@@ -1,12 +1,13 @@
 
 # Please note this file is autogenerated from generate_mozbuild.py, so do not modify it directly
 
 UNIFIED_SOURCES += [
+    'src/common/angleutils.cpp',
     'src/common/blocklayout.cpp',
     'src/common/debug.cpp',
     'src/common/event_tracer.cpp',
     'src/common/mathutil.cpp',
     'src/common/RefCountObject.cpp',
     'src/common/tls.cpp',
     'src/common/utilities.cpp',
     'src/compiler/preprocessor/DiagnosticsBase.cpp',
--- a/gfx/angle/src/angle.gypi
+++ b/gfx/angle/src/angle.gypi
@@ -21,16 +21,17 @@
         'libEGL.gypi'
     ],
 
     'targets':
     [
         {
             'target_name': 'copy_scripts',
             'type': 'none',
+            'hard_dependency': 1,
             'copies':
             [
                 {
                     'destination': '<(angle_gen_path)',
                     'files': [ 'copy_compiler_dll.bat', '<(angle_id_script_base)' ],
                 },
             ],
         },
@@ -41,55 +42,57 @@
         {
             'targets':
             [
                 {
                     'target_name': 'commit_id',
                     'type': 'none',
                     'includes': [ '../build/common_defines.gypi', ],
                     'dependencies': [ 'copy_scripts', ],
+                    'hard_dependency': 1,
                     'actions':
                     [
                         {
                             'action_name': 'Generate ANGLE Commit ID Header',
                             'message': 'Generating ANGLE Commit ID',
                             # reference the git index as an input, so we rebuild on changes to the index
                             'inputs': [ '<(angle_id_script)', '<(angle_path)/.git/index' ],
                             'outputs': [ '<(angle_id_header)' ],
                             'msvs_cygwin_shell': 0,
                             'action':
                             [
                                 'python', '<(angle_id_script)', 'gen', '<(angle_path)', '<(angle_id_header)'
                             ],
                         },
                     ],
-                    'direct_dependent_settings':
+                    'all_dependent_settings':
                     {
                         'include_dirs':
                         [
                             '<(angle_gen_path)',
                         ],
                     },
                 }
             ]
         },
         { # angle_use_commit_id==0
             'targets':
             [
                 {
                     'target_name': 'commit_id',
                     'type': 'none',
+                    'hard_dependency': 1,
                     'copies':
                     [
                         {
                             'destination': '<(angle_gen_path)/id',
                             'files': [ '<(angle_id_header_base)' ]
                         }
                     ],
-                    'direct_dependent_settings':
+                    'all_dependent_settings':
                     {
                         'include_dirs':
                         [
                             '<(angle_gen_path)',
                         ],
                     },
                 }
             ]
--- a/gfx/angle/src/commit.h
+++ b/gfx/angle/src/commit.h
@@ -1,3 +1,3 @@
-#define ANGLE_COMMIT_HASH "9a22db4058f8"
+#define ANGLE_COMMIT_HASH "fc329b4537cf"
 #define ANGLE_COMMIT_HASH_SIZE 12
-#define ANGLE_COMMIT_DATE "2014-09-19 12:49:11 -0700"
+#define ANGLE_COMMIT_DATE "2014-10-09 15:05:59 -0400"
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/common/NativeWindow.h
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow.h: Defines NativeWindow, a class for managing and
+// performing operations on an EGLNativeWindowType.
+// It is used for HWND (Desktop Windows) and IInspectable objects
+//(Windows Store Applications).
+
+#ifndef COMMON_NATIVEWINDOW_H_
+#define COMMON_NATIVEWINDOW_H_
+
+#include <EGL/eglplatform.h>
+#include "common/debug.h"
+#include "common/platform.h"
+
+// DXGISwapChain and DXGIFactory are typedef'd to specific required
+// types. The HWND NativeWindow implementation requires IDXGISwapChain
+// and IDXGIFactory and the Windows Store NativeWindow
+// implementation requires IDXGISwapChain1 and IDXGIFactory2.
+typedef IDXGISwapChain DXGISwapChain;
+typedef IDXGIFactory DXGIFactory;
+
+namespace rx
+{
+class NativeWindow
+{
+  public:
+    explicit NativeWindow(EGLNativeWindowType window);
+
+    // The HWND NativeWindow implementation can benefit
+    // by having inline versions of these methods to
+    // reduce the calling overhead.
+    inline bool initialize() { return true; }
+    inline bool getClientRect(LPRECT rect) { return GetClientRect(mWindow, rect) == TRUE; }
+    inline bool isIconic() { return IsIconic(mWindow) == TRUE; }
+
+    HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
+                            DXGI_FORMAT format, UINT width, UINT height,
+                            DXGISwapChain** swapChain);
+
+    inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
+
+  private:
+    EGLNativeWindowType mWindow;
+};
+}
+
+bool isValidEGLNativeWindowType(EGLNativeWindowType window);
+
+#endif // COMMON_NATIVEWINDOW_H_
--- a/gfx/angle/src/common/angleutils.cpp
+++ b/gfx/angle/src/common/angleutils.cpp
@@ -19,17 +19,17 @@ std::string FormatString(const char *fmt
         // Buffer was not large enough, calculate the required size and resize the buffer
         len = vsnprintf(NULL, 0, fmt, vararg);
         buffer.resize(len + 1);
 
         // Print again
         vsnprintf(&buffer[0], buffer.size(), fmt, vararg);
     }
 
-    return std::string(buffer.data(), len);
+    return std::string(&buffer[0], len);
 }
 
 std::string FormatString(const char *fmt, ...)
 {
     va_list vararg;
     va_start(vararg, fmt);
     std::string result = FormatString(fmt, vararg);
     va_end(vararg);
--- a/gfx/angle/src/common/debug.cpp
+++ b/gfx/angle/src/common/debug.cpp
@@ -82,28 +82,30 @@ bool perfActive()
     return active;
 #else
     return false;
 #endif
 }
 
 ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
 {
-#if defined(ANGLE_ENABLE_PERF)
 #if !defined(ANGLE_ENABLE_TRACE)
     if (!perfActive())
     {
         return;
     }
 #endif // !ANGLE_ENABLE_TRACE
     va_list vararg;
     va_start(vararg, format);
+#if defined(ANGLE_ENABLE_PERF)
     output(true, reinterpret_cast<PerfOutputFunction>(D3DPERF_BeginEvent), format, vararg);
+#else
+    output(true, NULL, format, vararg);
+#endif // ANGLE_ENABLE_PERF
     va_end(vararg);
-#endif // ANGLE_ENABLE_PERF
 }
 
 ScopedPerfEventHelper::~ScopedPerfEventHelper()
 {
 #if defined(ANGLE_ENABLE_PERF)
     if (perfActive())
     {
         D3DPERF_EndEvent();
--- a/gfx/angle/src/common/debug.h
+++ b/gfx/angle/src/common/debug.h
@@ -86,16 +86,20 @@ namespace gl
 #ifndef ANGLE_ENABLE_TRACE
 #define UNUSED_TRACE_VARIABLE(variable) ((void)variable)
 #else
 #define UNUSED_TRACE_VARIABLE(variable)
 #endif
 
 // 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
 // This will allow us to test with some automated test suites (eg dEQP) without crashing
 #ifndef NOASSERT_UNIMPLEMENTED
 #define NOASSERT_UNIMPLEMENTED 0
 #endif
 
 #if !defined(NDEBUG)
 #define UNIMPLEMENTED() do { \
--- a/gfx/angle/src/common/mathutil.h
+++ b/gfx/angle/src/common/mathutil.h
@@ -502,22 +502,22 @@ inline unsigned int averageFloat10(unsig
 
 namespace rx
 {
 
 template <typename T>
 struct Range
 {
     Range() {}
-    Range(T lo, T hi) : start(lo), end(hi) { }
+    Range(T lo, T hi) : start(lo), end(hi) { ASSERT(lo <= hi); }
 
     T start;
     T end;
 
-    T length() const { return (end > start ? (end - start) : 0); }
+    T length() const { return end - start; }
 };
 
 typedef Range<int> RangeI;
 typedef Range<unsigned int> RangeUI;
 
 template <typename T>
 T roundUp(const T value, const T alignment)
 {
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/common/win32/NativeWindow.cpp
@@ -0,0 +1,51 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow.cpp: Handler for managing HWND native window types.
+
+#include "common/NativeWindow.h"
+#include "common/debug.h"
+
+bool isValidEGLNativeWindowType(EGLNativeWindowType window)
+{
+    return (IsWindow(window) == TRUE);
+}
+
+namespace rx
+{
+NativeWindow::NativeWindow(EGLNativeWindowType window) : mWindow(window)
+{
+}
+
+HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory,
+                                      DXGI_FORMAT format, unsigned int width, unsigned int height,
+                                      DXGISwapChain** swapChain)
+{
+    if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
+    {
+        return E_INVALIDARG;
+    }
+
+    DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
+    swapChainDesc.BufferCount = 1;
+    swapChainDesc.BufferDesc.Format = format;
+    swapChainDesc.BufferDesc.Width = width;
+    swapChainDesc.BufferDesc.Height = height;
+    swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+    swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+    swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
+    swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
+    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
+    swapChainDesc.Flags = 0;
+    swapChainDesc.OutputWindow = mWindow;
+    swapChainDesc.SampleDesc.Count = 1;
+    swapChainDesc.SampleDesc.Quality = 0;
+    swapChainDesc.Windowed = TRUE;
+    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+
+    return factory->CreateSwapChain(device, &swapChainDesc, swapChain);
+}
+};
\ No newline at end of file
--- a/gfx/angle/src/compiler.gypi
+++ b/gfx/angle/src/compiler.gypi
@@ -19,16 +19,17 @@
             '../include/GLES3/gl3platform.h',
             '../include/GLSLANG/ShaderLang.h',
             '../include/GLSLANG/ShaderVars.h',
             '../include/KHR/khrplatform.h',
             '../include/angle_gl.h',
             'common/RefCountObject.cpp',
             'common/RefCountObject.h',
             'common/angleutils.h',
+            'common/angleutils.cpp',
             'common/blocklayout.cpp',
             'common/blocklayout.h',
             'common/debug.cpp',
             'common/debug.h',
             'common/event_tracer.cpp',
             'common/event_tracer.h',
             'common/mathutil.cpp',
             'common/mathutil.h',
--- a/gfx/angle/src/compiler/translator/Compiler.cpp
+++ b/gfx/angle/src/compiler/translator/Compiler.cpp
@@ -497,28 +497,28 @@ bool TCompiler::enforceVertexShaderTimin
 {
     RestrictVertexShaderTiming restrictor(infoSink.info);
     restrictor.enforceRestrictions(root);
     return restrictor.numErrors() == 0;
 }
 
 void TCompiler::collectVariables(TIntermNode* root)
 {
-    CollectVariables collect(&attributes,
-                             &outputVariables,
-                             &uniforms,
-                             &varyings,
-                             &interfaceBlocks,
-                             hashFunction);
+    sh::CollectVariables collect(&attributes,
+                                 &outputVariables,
+                                 &uniforms,
+                                 &varyings,
+                                 &interfaceBlocks,
+                                 hashFunction);
     root->traverse(&collect);
 
     // For backwards compatiblity with ShGetVariableInfo, expand struct
     // uniforms and varyings into separate variables for each field.
-    ExpandVariables(uniforms, &expandedUniforms);
-    ExpandVariables(varyings, &expandedVaryings);
+    sh::ExpandVariables(uniforms, &expandedUniforms);
+    sh::ExpandVariables(varyings, &expandedVaryings);
 }
 
 bool TCompiler::enforcePackingRestrictions()
 {
     VariablePacker packer;
     return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, expandedUniforms);
 }
 
--- a/gfx/angle/src/compiler/translator/Compiler.h
+++ b/gfx/angle/src/compiler/translator/Compiler.h
@@ -78,16 +78,19 @@ class TCompiler : public TShHandleBase
 
     ShHashFunction64 getHashFunction() const { return hashFunction; }
     NameMap& getNameMap() { return nameMap; }
     TSymbolTable& getSymbolTable() { return symbolTable; }
     ShShaderSpec getShaderSpec() const { return shaderSpec; }
     ShShaderOutput getOutputType() const { return outputType; }
     std::string getBuiltInResourcesString() const { return builtInResourcesString; }
 
+    // Get the resources set by InitBuiltInSymbolTable
+    const ShBuiltInResources& getResources() const;
+
   protected:
     sh::GLenum getShaderType() const { return shaderType; }
     // Initialize symbol-table with built-in symbols.
     bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
     // Compute the string representation of the built-in resources
     void setResourceString();
     // Clears the results from the previous compilation.
     void clearResults();
@@ -123,18 +126,16 @@ class TCompiler : public TShHandleBase
     bool enforceVertexShaderTimingRestrictions(TIntermNode* root);
     // Returns true if the shader does not use sampler dependent values to affect control
     // flow or in operations whose time can depend on the input values.
     bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
     // Return true if the maximum expression complexity is below the limit.
     bool limitExpressionComplexity(TIntermNode* root);
     // Get built-in extensions with default behavior.
     const TExtensionBehavior& getExtensionBehavior() const;
-    // Get the resources set by InitBuiltInSymbolTable
-    const ShBuiltInResources& getResources() const;
 
     const ArrayBoundsClamper& getArrayBoundsClamper() const;
     ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
     const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
 
     std::vector<sh::Attribute> attributes;
     std::vector<sh::Attribute> outputVariables;
     std::vector<sh::Uniform> uniforms;
--- a/gfx/angle/src/compiler/translator/OutputHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/OutputHLSL.cpp
@@ -16,36 +16,25 @@
 #include "compiler/translator/UnfoldShortCircuit.h"
 #include "compiler/translator/FlagStd140Structs.h"
 #include "compiler/translator/NodeSearch.h"
 #include "compiler/translator/RewriteElseBlocks.h"
 #include "compiler/translator/UtilsHLSL.h"
 #include "compiler/translator/util.h"
 #include "compiler/translator/UniformHLSL.h"
 #include "compiler/translator/StructureHLSL.h"
+#include "compiler/translator/TranslatorHLSL.h"
 
 #include <algorithm>
 #include <cfloat>
 #include <stdio.h>
 
 namespace sh
 {
 
-static sh::Attribute MakeAttributeFromType(const TType &type, const TString &name)
-{
-    sh::Attribute attributeVar;
-    attributeVar.type = GLVariableType(type);
-    attributeVar.precision = GLVariablePrecision(type);
-    attributeVar.name = name.c_str();
-    attributeVar.arraySize = static_cast<unsigned int>(type.getArraySize());
-    attributeVar.location = type.getLayoutQualifier().location;
-
-    return attributeVar;
-}
-
 TString OutputHLSL::TextureFunction::name() const
 {
     TString name = "gl_texture";
 
     if (IsSampler2D(sampler))
     {
         name += "2D";
     }
@@ -100,18 +89,20 @@ bool OutputHLSL::TextureFunction::operat
     if (offset && !rhs.offset) return false;
 
     if (method < rhs.method)   return true;
     if (method > rhs.method)   return false;
 
     return false;
 }
 
-OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType)
-    : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType)
+OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator)
+    : TIntermTraverser(true, true, true),
+      mContext(context),
+      mOutputType(parentTranslator->getOutputType())
 {
     mUnfoldShortCircuit = new UnfoldShortCircuit(context, this);
     mInsideFunction = false;
 
     mUsesFragColor = false;
     mUsesFragData = false;
     mUsesDepthRange = false;
     mUsesFragCoord = false;
@@ -133,29 +124,30 @@ OutputHLSL::OutputHLSL(TParseContext &co
     mUsesFaceforward4 = false;
     mUsesAtan2_1 = false;
     mUsesAtan2_2 = false;
     mUsesAtan2_3 = false;
     mUsesAtan2_4 = false;
     mUsesDiscardRewriting = false;
     mUsesNestedBreak = false;
 
+    const ShBuiltInResources &resources = parentTranslator->getResources();
     mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
 
     mUniqueIndex = 0;
 
     mContainsLoopDiscontinuity = false;
     mOutputLod0Function = false;
     mInsideDiscontinuousLoop = false;
     mNestedLoopDepth = 0;
 
     mExcessiveLoopIndex = NULL;
 
     mStructureHLSL = new StructureHLSL;
-    mUniformHLSL = new UniformHLSL(mStructureHLSL, mOutputType);
+    mUniformHLSL = new UniformHLSL(mStructureHLSL, parentTranslator);
 
     if (mOutputType == SH_HLSL9_OUTPUT)
     {
         if (mContext.shaderType == GL_FRAGMENT_SHADER)
         {
             // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront
             mUniformHLSL->reserveUniformRegisters(3);
         }
@@ -219,41 +211,16 @@ void OutputHLSL::makeFlaggedStructMaps(c
     }
 }
 
 TInfoSinkBase &OutputHLSL::getBodyStream()
 {
     return mBody;
 }
 
-const std::vector<sh::Uniform> &OutputHLSL::getUniforms()
-{
-    return mUniformHLSL->getUniforms();
-}
-
-const std::vector<sh::InterfaceBlock> &OutputHLSL::getInterfaceBlocks() const
-{
-    return mUniformHLSL->getInterfaceBlocks();
-}
-
-const std::vector<sh::Attribute> &OutputHLSL::getOutputVariables() const
-{
-    return mActiveOutputVariables;
-}
-
-const std::vector<sh::Attribute> &OutputHLSL::getAttributes() const
-{
-    return mActiveAttributes;
-}
-
-const std::vector<sh::Varying> &OutputHLSL::getVaryings() const
-{
-    return mActiveVaryings;
-}
-
 const std::map<std::string, unsigned int> &OutputHLSL::getInterfaceBlockRegisterMap() const
 {
     return mUniformHLSL->getInterfaceBlockRegisterMap();
 }
 
 const std::map<std::string, unsigned int> &OutputHLSL::getUniformRegisterMap() const
 {
     return mUniformHLSL->getUniformRegisterMap();
@@ -331,29 +298,24 @@ void OutputHLSL::header()
     for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++)
     {
         const TType &type = varying->second->getType();
         const TString &name = varying->second->getSymbol();
 
         // Program linking depends on this exact format
         varyings += "static " + InterpolationString(type.getQualifier()) + " " + TypeString(type) + " " +
                     Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n";
-
-        declareVaryingToList(type, type.getQualifier(), name, mActiveVaryings);
     }
 
     for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++)
     {
         const TType &type = attribute->second->getType();
         const TString &name = attribute->second->getSymbol();
 
         attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n";
-
-        sh::Attribute attributeVar = MakeAttributeFromType(type, name);
-        mActiveAttributes.push_back(attributeVar);
     }
 
     out << mStructureHLSL->structsHeader();
 
     out << mUniformHLSL->uniformsHeader(mOutputType, mReferencedUniforms);
     out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks);
 
     if (mUsesDiscardRewriting)
@@ -379,19 +341,16 @@ void OutputHLSL::header()
         {
             for (ReferencedSymbols::const_iterator outputVariableIt = mReferencedOutputVariables.begin(); outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++)
             {
                 const TString &variableName = outputVariableIt->first;
                 const TType &variableType = outputVariableIt->second->getType();
 
                 out << "static " + TypeString(variableType) + " out_" + variableName + ArrayString(variableType) +
                        " = " + initializer(variableType) + ";\n";
-
-                sh::Attribute outputVar = MakeAttributeFromType(variableType, variableName);
-                mActiveOutputVariables.push_back(outputVar);
             }
         }
         else
         {
             const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
 
             out << "static float4 gl_Color[" << numColorValues << "] =\n"
                    "{\n";
@@ -2917,17 +2876,9 @@ const ConstantUnion *OutputHLSL::writeCo
         {
             out << ")";
         }
     }
 
     return constUnion;
 }
 
-void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQualifier,
-                                      const TString &name, std::vector<Varying> &fieldsOut)
-{
-    GetVariableTraverser traverser;
-    traverser.traverse(type, name, &fieldsOut);
-    fieldsOut.back().interpolation = GetInterpolationType(baseTypeQualifier);
 }
-
-}
--- a/gfx/angle/src/compiler/translator/OutputHLSL.h
+++ b/gfx/angle/src/compiler/translator/OutputHLSL.h
@@ -22,27 +22,22 @@ class UnfoldShortCircuit;
 class StructureHLSL;
 class UniformHLSL;
 
 typedef std::map<TString, TIntermSymbol*> ReferencedSymbols;
 
 class OutputHLSL : public TIntermTraverser
 {
   public:
-    OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType);
+    OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator);
     ~OutputHLSL();
 
     void output();
 
     TInfoSinkBase &getBodyStream();
-    const std::vector<sh::Uniform> &getUniforms();
-    const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const;
-    const std::vector<sh::Attribute> &getOutputVariables() const;
-    const std::vector<sh::Attribute> &getAttributes() const;
-    const std::vector<sh::Varying> &getVaryings() const;
 
     const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const;
     const std::map<std::string, unsigned int> &getUniformRegisterMap() const;
 
     static TString initializer(const TType &type);
 
   protected:
     void header();
@@ -150,23 +145,18 @@ class OutputHLSL : public TIntermTravers
 
     bool mContainsLoopDiscontinuity;
     bool mOutputLod0Function;
     bool mInsideDiscontinuousLoop;
     int mNestedLoopDepth;
 
     TIntermSymbol *mExcessiveLoopIndex;
 
-    void declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector<sh::Varying>& fieldsOut);
-
     TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName);
 
-    std::vector<sh::Attribute> mActiveOutputVariables;
-    std::vector<sh::Attribute> mActiveAttributes;
-    std::vector<sh::Varying> mActiveVaryings;
     std::map<TIntermTyped*, TString> mFlaggedStructMappedNames;
     std::map<TIntermTyped*, TString> mFlaggedStructOriginalNames;
 
     void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs);
 };
 
 }
 
--- a/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/TranslatorHLSL.cpp
@@ -12,26 +12,20 @@
 TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
     : TCompiler(type, spec, output)
 {
 }
 
 void TranslatorHLSL::translate(TIntermNode *root)
 {
     TParseContext& parseContext = *GetGlobalParseContext();
-    sh::OutputHLSL outputHLSL(parseContext, getResources(), getOutputType());
+    sh::OutputHLSL outputHLSL(parseContext, this);
 
     outputHLSL.output();
 
-    attributes      = outputHLSL.getAttributes();
-    outputVariables = outputHLSL.getOutputVariables();
-    uniforms        = outputHLSL.getUniforms();
-    varyings        = outputHLSL.getVaryings();
-    interfaceBlocks = outputHLSL.getInterfaceBlocks();
-
     mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap();
     mUniformRegisterMap = outputHLSL.getUniformRegisterMap();
 }
 
 bool TranslatorHLSL::hasInterfaceBlock(const std::string &interfaceBlockName) const
 {
     return (mInterfaceBlockRegisterMap.count(interfaceBlockName) > 0);
 }
--- a/gfx/angle/src/compiler/translator/UniformHLSL.cpp
+++ b/gfx/angle/src/compiler/translator/UniformHLSL.cpp
@@ -9,16 +9,17 @@
 
 #include "OutputHLSL.h"
 #include "common/blocklayout.h"
 #include "common/utilities.h"
 #include "compiler/translator/UniformHLSL.h"
 #include "compiler/translator/StructureHLSL.h"
 #include "compiler/translator/util.h"
 #include "compiler/translator/UtilsHLSL.h"
+#include "compiler/translator/TranslatorHLSL.h"
 
 namespace sh
 {
 
 static const char *UniformRegisterPrefix(const TType &type)
 {
     if (IsSampler(type.getBasicType()))
     {
@@ -55,46 +56,61 @@ static TString InterfaceBlockFieldTypeSt
     }
 }
 
 static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
 {
     return DecoratePrivate(interfaceBlock.name()) + "_type";
 }
 
-UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType)
+UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator)
     : mUniformRegister(0),
       mInterfaceBlockRegister(0),
       mSamplerRegister(0),
       mStructureHLSL(structureHLSL),
-      mOutputType(outputType)
+      mOutputType(translator->getOutputType()),
+      mUniforms(translator->getUniforms())
 {}
 
 void UniformHLSL::reserveUniformRegisters(unsigned int registerCount)
 {
     mUniformRegister = registerCount;
 }
 
 void UniformHLSL::reserveInterfaceBlockRegisters(unsigned int registerCount)
 {
     mInterfaceBlockRegister = registerCount;
 }
 
+const Uniform *UniformHLSL::findUniformByName(const TString &name) const
+{
+    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
+    {
+        if (mUniforms[uniformIndex].name == name.c_str())
+        {
+            return &mUniforms[uniformIndex];
+        }
+    }
+
+    UNREACHABLE();
+    return NULL;
+}
+
 unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
 {
     unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
 
-    GetVariableTraverser traverser;
-    traverser.traverse(type, name, &mActiveUniforms);
+    const Uniform *uniform = findUniformByName(name);
+    ASSERT(uniform);
 
-    const sh::Uniform &activeUniform = mActiveUniforms.back();
-    mUniformRegisterMap[activeUniform.name] = registerIndex;
+    mUniformRegisterMap[uniform->name] = registerIndex;
 
-    unsigned int registerCount = HLSLVariableRegisterCount(activeUniform, mOutputType);
-    if (IsSampler(type.getBasicType()))
+    unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
+
+    if (gl::IsSampler(uniform->type))
     {
         mSamplerRegister += registerCount;
     }
     else
     {
         mUniformRegister += registerCount;
     }
 
@@ -149,33 +165,20 @@ TString UniformHLSL::interfaceBlocksHead
          interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++)
     {
         const TType &nodeType = interfaceBlockIt->second->getType();
         const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock();
 
         unsigned int arraySize = static_cast<unsigned int>(interfaceBlock.arraySize());
         unsigned int activeRegister = mInterfaceBlockRegister;
 
-        InterfaceBlock activeBlock;
-        activeBlock.name = interfaceBlock.name().c_str();
-        activeBlock.arraySize = arraySize;
-
-        GetInterfaceBlockFields(interfaceBlock, &activeBlock.fields);
-
-        mInterfaceBlockRegisterMap[activeBlock.name] = activeRegister;
+        mInterfaceBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister;
         mInterfaceBlockRegister += std::max(1u, arraySize);
 
-        activeBlock.layout = GetBlockLayoutType(interfaceBlock.blockStorage());
-
-        if (interfaceBlock.matrixPacking() == EmpRowMajor)
-        {
-            activeBlock.isRowMajorLayout = true;
-        }
-
-        mActiveInterfaceBlocks.push_back(activeBlock);
+        // FIXME: interface block field names
 
         if (interfaceBlock.hasInstanceName())
         {
             interfaceBlocks += interfaceBlockStructString(interfaceBlock);
         }
 
         if (arraySize > 0)
         {
--- a/gfx/angle/src/compiler/translator/UniformHLSL.h
+++ b/gfx/angle/src/compiler/translator/UniformHLSL.h
@@ -14,52 +14,50 @@
 
 namespace sh
 {
 class StructureHLSL;
 
 class UniformHLSL
 {
   public:
-    UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType);
+    UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator);
 
     void reserveUniformRegisters(unsigned int registerCount);
     void reserveInterfaceBlockRegisters(unsigned int registerCount);
     TString uniformsHeader(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::vector<Uniform> &getUniforms() const { return mActiveUniforms; }
-    const std::vector<InterfaceBlock> &getInterfaceBlocks() const { return mActiveInterfaceBlocks; }
     const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const
     {
         return mInterfaceBlockRegisterMap;
     }
     const std::map<std::string, unsigned int> &getUniformRegisterMap() const
     {
         return mUniformRegisterMap;
     }
 
   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 mUniformRegister;
     unsigned int mInterfaceBlockRegister;
     unsigned int mSamplerRegister;
     StructureHLSL *mStructureHLSL;
     ShShaderOutput mOutputType;
 
-    std::vector<Uniform> mActiveUniforms;
-    std::vector<InterfaceBlock> mActiveInterfaceBlocks;
+    const std::vector<Uniform> &mUniforms;
     std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
     std::map<std::string, unsigned int> mUniformRegisterMap;
 };
 
 }
 
 #endif // TRANSLATOR_UNIFORMHLSL_H_
--- a/gfx/angle/src/compiler/translator/VariableInfo.cpp
+++ b/gfx/angle/src/compiler/translator/VariableInfo.cpp
@@ -4,47 +4,76 @@
 // found in the LICENSE file.
 //
 
 #include "angle_gl.h"
 #include "compiler/translator/VariableInfo.h"
 #include "compiler/translator/util.h"
 #include "common/utilities.h"
 
-static void ExpandUserDefinedVariable(const sh::ShaderVariable &variable,
-                                      const std::string &name,
-                                      const std::string &mappedName,
-                                      bool markStaticUse,
-                                      std::vector<sh::ShaderVariable> *expanded);
+namespace sh
+{
+
+namespace
+{
+
+TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field)
+{
+    if (interfaceBlock.hasInstanceName())
+    {
+        return interfaceBlock.name() + "." + field.name();
+    }
+    else
+    {
+        return field.name();
+    }
+}
 
-static void ExpandVariable(const sh::ShaderVariable &variable,
-                           const std::string &name,
-                           const std::string &mappedName,
-                           bool markStaticUse,
-                           std::vector<sh::ShaderVariable> *expanded)
+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;
+    }
+}
+
+void ExpandUserDefinedVariable(const ShaderVariable &variable,
+                               const std::string &name,
+                               const std::string &mappedName,
+                               bool markStaticUse,
+                               std::vector<ShaderVariable> *expanded);
+
+void ExpandVariable(const ShaderVariable &variable,
+                    const std::string &name,
+                    const std::string &mappedName,
+                    bool markStaticUse,
+                    std::vector<ShaderVariable> *expanded)
 {
     if (variable.isStruct())
     {
         if (variable.isArray())
         {
             for (size_t elementIndex = 0; elementIndex < variable.elementCount(); elementIndex++)
             {
-                std::string lname = name + ArrayString(elementIndex);
-                std::string lmappedName = mappedName + ArrayString(elementIndex);
+                std::string lname = name + ::ArrayString(elementIndex);
+                std::string lmappedName = mappedName + ::ArrayString(elementIndex);
                 ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
             }
         }
         else
         {
             ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
         }
     }
     else
     {
-        sh::ShaderVariable expandedVar = variable;
+        ShaderVariable expandedVar = variable;
 
         expandedVar.name = name;
         expandedVar.mappedName = mappedName;
 
         // Mark all expanded fields as used if the parent is used
         if (markStaticUse)
         {
             expandedVar.staticUse = true;
@@ -55,51 +84,53 @@ static void ExpandVariable(const sh::Sha
             expandedVar.name += "[0]";
             expandedVar.mappedName += "[0]";
         }
 
         expanded->push_back(expandedVar);
     }
 }
 
-static void ExpandUserDefinedVariable(const sh::ShaderVariable &variable,
-                                      const std::string &name,
-                                      const std::string &mappedName,
-                                      bool markStaticUse,
-                                      std::vector<sh::ShaderVariable> *expanded)
+void ExpandUserDefinedVariable(const ShaderVariable &variable,
+                               const std::string &name,
+                               const std::string &mappedName,
+                               bool markStaticUse,
+                               std::vector<ShaderVariable> *expanded)
 {
     ASSERT(variable.isStruct());
 
-    const std::vector<sh::ShaderVariable> &fields = variable.fields;
+    const std::vector<ShaderVariable> &fields = variable.fields;
 
     for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
     {
-        const sh::ShaderVariable &field = fields[fieldIndex];
+        const ShaderVariable &field = fields[fieldIndex];
         ExpandVariable(field,
                        name + "." + field.name,
                        mappedName + "." + field.mappedName,
                        markStaticUse,
                        expanded);
     }
 }
 
 template <class VarT>
-static VarT *FindVariable(const TString &name,
-                          std::vector<VarT> *infoList)
+VarT *FindVariable(const TString &name,
+                  std::vector<VarT> *infoList)
 {
     // TODO(zmo): optimize this function.
     for (size_t ii = 0; ii < infoList->size(); ++ii)
     {
         if ((*infoList)[ii].name.c_str() == name)
             return &((*infoList)[ii]);
     }
 
     return NULL;
 }
 
+}
+
 CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
                                    std::vector<sh::Attribute> *outputVariables,
                                    std::vector<sh::Uniform> *uniforms,
                                    std::vector<sh::Varying> *varyings,
                                    std::vector<sh::InterfaceBlock> *interfaceBlocks,
                                    ShHashFunction64 hashFunction)
     : mAttribs(attribs),
       mOutputVariables(outputVariables),
@@ -116,20 +147,20 @@ CollectVariables::CollectVariables(std::
 // We want to check whether a uniform/varying is statically used
 // because we only count the used ones in packing computing.
 // Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
 // toward varying counting if they are statically used in a fragment
 // shader.
 void CollectVariables::visitSymbol(TIntermSymbol *symbol)
 {
     ASSERT(symbol != NULL);
-    sh::ShaderVariable *var = NULL;
+    ShaderVariable *var = NULL;
     const TString &symbolName = symbol->getSymbol();
 
-    if (sh::IsVarying(symbol->getQualifier()))
+    if (IsVarying(symbol->getQualifier()))
     {
         var = FindVariable(symbolName, mVaryings);
     }
     else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
     {
         UNREACHABLE();
     }
     else
@@ -143,17 +174,17 @@ void CollectVariables::visitSymbol(TInte
           case EvqFragmentOut:
             var = FindVariable(symbolName, mOutputVariables);
             break;
           case EvqUniform:
             {
                 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
                 if (interfaceBlock)
                 {
-                    sh::InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
+                    InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
                     ASSERT(namedBlock);
                     var = FindVariable(symbolName, &namedBlock->fields);
 
                     // Set static use on the parent interface block here
                     namedBlock->staticUse = true;
 
                 }
                 else
@@ -163,45 +194,45 @@ void CollectVariables::visitSymbol(TInte
 
                 // It's an internal error to reference an undefined user uniform
                 ASSERT(symbolName.compare(0, 3, "gl_") == 0 || var);
             }
             break;
           case EvqFragCoord:
             if (!mFragCoordAdded)
             {
-                sh::Varying info;
+                Varying info;
                 info.name = "gl_FragCoord";
                 info.mappedName = "gl_FragCoord";
                 info.type = GL_FLOAT_VEC4;
                 info.arraySize = 0;
                 info.precision = GL_MEDIUM_FLOAT;  // Use mediump as it doesn't really matter.
                 info.staticUse = true;
                 mVaryings->push_back(info);
                 mFragCoordAdded = true;
             }
             return;
           case EvqFrontFacing:
             if (!mFrontFacingAdded)
             {
-                sh::Varying info;
+                Varying info;
                 info.name = "gl_FrontFacing";
                 info.mappedName = "gl_FrontFacing";
                 info.type = GL_BOOL;
                 info.arraySize = 0;
                 info.precision = GL_NONE;
                 info.staticUse = true;
                 mVaryings->push_back(info);
                 mFrontFacingAdded = true;
             }
             return;
           case EvqPointCoord:
             if (!mPointCoordAdded)
             {
-                sh::Varying info;
+                Varying info;
                 info.name = "gl_PointCoord";
                 info.mappedName = "gl_PointCoord";
                 info.type = GL_FLOAT_VEC2;
                 info.arraySize = 0;
                 info.precision = GL_MEDIUM_FLOAT;  // Use mediump as it doesn't really matter.
                 info.staticUse = true;
                 mVaryings->push_back(info);
                 mPointCoordAdded = true;
@@ -212,73 +243,85 @@ void CollectVariables::visitSymbol(TInte
         }
     }
     if (var)
     {
         var->staticUse = true;
     }
 }
 
-class NameHashingTraverser : public sh::GetVariableTraverser
+class NameHashingTraverser : public GetVariableTraverser
 {
   public:
     NameHashingTraverser(ShHashFunction64 hashFunction)
         : mHashFunction(hashFunction)
     {}
 
   private:
     DISALLOW_COPY_AND_ASSIGN(NameHashingTraverser);
 
-    virtual void visitVariable(sh::ShaderVariable *variable)
+    virtual void visitVariable(ShaderVariable *variable)
     {
         TString stringName = TString(variable->name.c_str());
         variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str();
     }
 
     ShHashFunction64 mHashFunction;
 };
 
 // Attributes, which cannot have struct fields, are a special case
 template <>
 void CollectVariables::visitVariable(const TIntermSymbol *variable,
-                                     std::vector<sh::Attribute> *infoList) const
+                                     std::vector<Attribute> *infoList) const
 {
     ASSERT(variable);
     const TType &type = variable->getType();
     ASSERT(!type.getStruct());
 
-    sh::Attribute attribute;
+    Attribute attribute;
 
-    attribute.type = sh::GLVariableType(type);
-    attribute.precision = sh::GLVariablePrecision(type);
+    attribute.type = GLVariableType(type);
+    attribute.precision = GLVariablePrecision(type);
     attribute.name = variable->getSymbol().c_str();
     attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
     attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
     attribute.location = variable->getType().getLayoutQualifier().location;
 
     infoList->push_back(attribute);
 }
 
 template <>
 void CollectVariables::visitVariable(const TIntermSymbol *variable,
-                                     std::vector<sh::InterfaceBlock> *infoList) const
+                                     std::vector<InterfaceBlock> *infoList) const
 {
-    sh::InterfaceBlock interfaceBlock;
+    InterfaceBlock interfaceBlock;
     const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock();
     ASSERT(blockType);
 
     interfaceBlock.name = blockType->name().c_str();
     interfaceBlock.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
     interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
     interfaceBlock.arraySize = variable->getArraySize();
     interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
-    interfaceBlock.layout = sh::GetBlockLayoutType(blockType->blockStorage());
+    interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
 
     // Gather field information
-    sh::GetInterfaceBlockFields(*blockType, &interfaceBlock.fields);
+    const TFieldList &fieldList = blockType->fields();
+
+    for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex)
+    {
+        const TField &field = *fieldList[fieldIndex];
+        const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field);
+        const TType &fieldType = *field.type();
+
+        GetVariableTraverser traverser;
+        traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields);
+
+        interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
+    }
 
     infoList->push_back(interfaceBlock);
 }
 
 template <typename VarT>
 void CollectVariables::visitVariable(const TIntermSymbol *variable,
                                      std::vector<VarT> *infoList) const
 {
@@ -319,17 +362,17 @@ bool CollectVariables::visitAggregate(Vi
 
             if (typedNode.getBasicType() == EbtInterfaceBlock)
             {
                 visitInfoList(sequence, mInterfaceBlocks);
                 visitChildren = false;
             }
             else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
                      qualifier == EvqFragmentOut || qualifier == EvqUniform ||
-                     sh::IsVarying(qualifier))
+                     IsVarying(qualifier))
             {
                 switch (qualifier)
                 {
                   case EvqAttribute:
                   case EvqVertexIn:
                     visitInfoList(sequence, mAttribs);
                     break;
                   case EvqFragmentOut:
@@ -360,34 +403,36 @@ bool CollectVariables::visitBinary(Visit
         // NOTE: we do not determine static use for individual blocks of an array
         TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
         ASSERT(blockNode);
 
         TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
         ASSERT(constantUnion);
 
         const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
-        sh::InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
+        InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
         ASSERT(namedBlock);
         namedBlock->staticUse = true;
 
         unsigned int fieldIndex = constantUnion->getUConst(0);
         ASSERT(fieldIndex < namedBlock->fields.size());
         namedBlock->fields[fieldIndex].staticUse = true;
         return false;
     }
 
     return true;
 }
 
 template <typename VarT>
 void ExpandVariables(const std::vector<VarT> &compact,
-                     std::vector<sh::ShaderVariable> *expanded)
+                     std::vector<ShaderVariable> *expanded)
 {
     for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
     {
-        const sh::ShaderVariable &variable = compact[variableIndex];
+        const ShaderVariable &variable = compact[variableIndex];
         ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
     }
 }
 
-template void ExpandVariables(const std::vector<sh::Uniform> &, std::vector<sh::ShaderVariable> *);
-template void ExpandVariables(const std::vector<sh::Varying> &, std::vector<sh::ShaderVariable> *);
+template void ExpandVariables(const std::vector<Uniform> &, std::vector<ShaderVariable> *);
+template void ExpandVariables(const std::vector<Varying> &, std::vector<ShaderVariable> *);
+
+}
--- a/gfx/angle/src/compiler/translator/VariableInfo.h
+++ b/gfx/angle/src/compiler/translator/VariableInfo.h
@@ -6,51 +6,56 @@
 
 #ifndef COMPILER_VARIABLE_INFO_H_
 #define COMPILER_VARIABLE_INFO_H_
 
 #include <GLSLANG/ShaderLang.h>
 
 #include "compiler/translator/IntermNode.h"
 
+namespace sh
+{
+
 // Traverses intermediate tree to collect all attributes, uniforms, varyings.
 class CollectVariables : public TIntermTraverser
 {
   public:
-    CollectVariables(std::vector<sh::Attribute> *attribs,
-                     std::vector<sh::Attribute> *outputVariables,
-                     std::vector<sh::Uniform> *uniforms,
-                     std::vector<sh::Varying> *varyings,
-                     std::vector<sh::InterfaceBlock> *interfaceBlocks,
+    CollectVariables(std::vector<Attribute> *attribs,
+                     std::vector<Attribute> *outputVariables,
+                     std::vector<Uniform> *uniforms,
+                     std::vector<Varying> *varyings,
+                     std::vector<InterfaceBlock> *interfaceBlocks,
                      ShHashFunction64 hashFunction);
 
     virtual void visitSymbol(TIntermSymbol *symbol);
     virtual bool visitAggregate(Visit, TIntermAggregate *node);
     virtual bool visitBinary(Visit visit, TIntermBinary *binaryNode);
 
   private:
     template <typename VarT>
     void visitVariable(const TIntermSymbol *variable, std::vector<VarT> *infoList) const;
 
     template <typename VarT>
     void visitInfoList(const TIntermSequence &sequence, std::vector<VarT> *infoList) const;
 
-    std::vector<sh::Attribute> *mAttribs;
-    std::vector<sh::Attribute> *mOutputVariables;
-    std::vector<sh::Uniform> *mUniforms;
-    std::vector<sh::Varying> *mVaryings;
-    std::vector<sh::InterfaceBlock> *mInterfaceBlocks;
+    std::vector<Attribute> *mAttribs;
+    std::vector<Attribute> *mOutputVariables;
+    std::vector<Uniform> *mUniforms;
+    std::vector<Varying> *mVaryings;
+    std::vector<InterfaceBlock> *mInterfaceBlocks;
 
-    std::map<std::string, sh::InterfaceBlockField *> mInterfaceBlockFields;
+    std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
 
     bool mPointCoordAdded;
     bool mFrontFacingAdded;
     bool mFragCoordAdded;
 
     ShHashFunction64 mHashFunction;
 };
 
 // Expand struct variables to flattened lists of split variables
 template <typename VarT>
 void ExpandVariables(const std::vector<VarT> &compact,
-                     std::vector<sh::ShaderVariable> *expanded);
+                     std::vector<ShaderVariable> *expanded);
+
+}
 
 #endif  // COMPILER_VARIABLE_INFO_H_
--- a/gfx/angle/src/compiler/translator/util.cpp
+++ b/gfx/angle/src/compiler/translator/util.cpp
@@ -315,49 +315,9 @@ void GetVariableTraverser::traverse(cons
     ASSERT(output);
     output->push_back(variable);
 }
 
 template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *);
 template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *);
 template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *);
 
-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;
-    }
 }
-
-static TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field)
-{
-    if (interfaceBlock.hasInstanceName())
-    {
-        return interfaceBlock.name() + "." + field.name();
-    }
-    else
-    {
-        return field.name();
-    }
-}
-
-void GetInterfaceBlockFields(const TInterfaceBlock &interfaceBlock, std::vector<InterfaceBlockField> *fieldsOut)
-{
-    const TFieldList &fieldList = interfaceBlock.fields();
-
-    for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex)
-    {
-        const TField &field = *fieldList[fieldIndex];
-        const TString &fullFieldName = InterfaceBlockFieldName(interfaceBlock, field);
-        const TType &fieldType = *field.type();
-
-        GetVariableTraverser traverser;
-        traverser.traverse(fieldType, fullFieldName, fieldsOut);
-
-        fieldsOut->back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
-    }
-}
-
-}
--- a/gfx/angle/src/compiler/translator/util.h
+++ b/gfx/angle/src/compiler/translator/util.h
@@ -28,17 +28,16 @@ namespace sh
 {
 
 GLenum GLVariableType(const TType &type);
 GLenum GLVariablePrecision(const TType &type);
 bool IsVaryingIn(TQualifier qualifier);
 bool IsVaryingOut(TQualifier qualifier);
 bool IsVarying(TQualifier qualifier);
 InterpolationType GetInterpolationType(TQualifier qualifier);
-BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage);
 TString ArrayString(const TType &type);
 
 class GetVariableTraverser
 {
   public:
     GetVariableTraverser() {}
 
     template <typename VarT>
@@ -47,13 +46,11 @@ class GetVariableTraverser
   protected:
     // May be overloaded
     virtual void visitVariable(ShaderVariable *newVar) {}
 
   private:
     DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser);
 };
 
-void GetInterfaceBlockFields(const TInterfaceBlock &interfaceBlock, std::vector<InterfaceBlockField> *fieldsOut);
-
 }
 
 #endif // COMPILER_UTIL_H
--- a/gfx/angle/src/libEGL.gypi
+++ b/gfx/angle/src/libEGL.gypi
@@ -29,21 +29,23 @@
             'common/angleutils.h',
             'common/debug.cpp',
             'common/debug.h',
             'common/event_tracer.cpp',
             'common/event_tracer.h',
             'common/mathutil.cpp',
             'common/mathutil.h',
             'common/platform.h',
+            'common/NativeWindow.h',
             'common/tls.cpp',
             'common/tls.h',
             'common/utilities.cpp',
             'common/utilities.h',
             'common/version.h',
+            'common/win32/NativeWindow.cpp',
             'libEGL/Config.cpp',
             'libEGL/Config.h',
             'libEGL/Display.cpp',
             'libEGL/Display.h',
             'libEGL/Surface.cpp',
             'libEGL/Surface.h',
             'libEGL/libEGL.cpp',
             'libEGL/libEGL.def',
--- a/gfx/angle/src/libEGL/Display.cpp
+++ b/gfx/angle/src/libEGL/Display.cpp
@@ -188,17 +188,17 @@ bool Display::getConfigAttrib(EGLConfig 
         return false;
     }
 
     return true;
 }
 
 
 
-EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList)
+EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList)
 {
     const Config *configuration = mConfigSet.get(config);
     EGLint postSubBufferSupported = EGL_FALSE;
 
     EGLint width = 0;
     EGLint height = 0;
     EGLint fixedSize = EGL_FALSE;
 
@@ -489,17 +489,17 @@ bool Display::isValidContext(gl::Context
     return mContextSet.find(context) != mContextSet.end();
 }
 
 bool Display::isValidSurface(egl::Surface *surface)
 {
     return mSurfaceSet.find(surface) != mSurfaceSet.end();
 }
 
-bool Display::hasExistingWindowSurface(HWND window)
+bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
 {
     for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
     {
         if ((*surface)->getWindowHandle() == window)
         {
             return true;
         }
     }
@@ -547,18 +547,20 @@ void Display::initDisplayExtensionString
     extensions.push_back("EGL_ANGLE_query_surface_pointer");
     extensions.push_back("EGL_ANGLE_window_fixed_size");
 
     if (mRenderer->getPostSubBufferSupport())
     {
         extensions.push_back("EGL_NV_post_sub_buffer");
     }
 
+#if defined (ANGLE_TEST_CONFIG)
     // TODO: complete support for the EGL_KHR_create_context extension
     extensions.push_back("EGL_KHR_create_context");
+#endif
 
     std::ostringstream stream;
     std::copy(extensions.begin(), extensions.end(), std::ostream_iterator<std::string>(stream, " "));
     mDisplayExtensionString = stream.str();
 }
 
 const char *Display::getExtensionString(egl::Display *display)
 {
--- a/gfx/angle/src/libEGL/Display.h
+++ b/gfx/angle/src/libEGL/Display.h
@@ -38,28 +38,28 @@ class Display
     static const char *getExtensionString(egl::Display *display);
 
     static bool supportsPlatformD3D();
     static bool supportsPlatformOpenGL();
 
     bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
     bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
 
-    EGLSurface createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList);
+    EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList);
     EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList);
     EGLContext createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
 
     void destroySurface(egl::Surface *surface);
     void destroyContext(gl::Context *context);
 
     bool isInitialized() const;
     bool isValidConfig(EGLConfig config);
     bool isValidContext(gl::Context *context);
     bool isValidSurface(egl::Surface *surface);
-    bool hasExistingWindowSurface(HWND window);
+    bool hasExistingWindowSurface(EGLNativeWindowType window);
 
     rx::Renderer *getRenderer() { return mRenderer; };
 
     // exported methods must be virtual
     virtual void notifyDeviceLost();
     virtual void recreateSwapChains();
 
     const char *getExtensionString() const;
--- a/gfx/angle/src/libEGL/Surface.cpp
+++ b/gfx/angle/src/libEGL/Surface.cpp
@@ -17,21 +17,23 @@
 #include "common/debug.h"
 #include "libGLESv2/Texture.h"
 #include "libGLESv2/renderer/SwapChain.h"
 #include "libGLESv2/main.h"
 
 #include "libEGL/main.h"
 #include "libEGL/Display.h"
 
+#include "common/NativeWindow.h"
+
 namespace egl
 {
 
-Surface::Surface(Display *display, const Config *config, HWND window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) 
-    : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
+Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) 
+    : mDisplay(display), mConfig(config), mNativeWindow(window), mPostSubBufferSupported(postSubBufferSupported)
 {
     mRenderer = mDisplay->getRenderer();
     mSwapChain = NULL;
     mShareHandle = NULL;
     mTexture = NULL;
     mTextureFormat = EGL_NO_TEXTURE;
     mTextureTarget = EGL_NO_TEXTURE;
 
@@ -43,17 +45,17 @@ Surface::Surface(Display *display, const
     mHeight = height;
     setSwapInterval(1);
     mFixedSize = fixedSize;
 
     subclassWindow();
 }
 
 Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
-    : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
+    : mDisplay(display), mNativeWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
 {
     mRenderer = mDisplay->getRenderer();
     mSwapChain = NULL;
     mWindowSubclassed = false;
     mTexture = NULL;
     mTextureFormat = textureFormat;
     mTextureTarget = textureType;
 
@@ -69,16 +71,24 @@ Surface::Surface(Display *display, const
 Surface::~Surface()
 {
     unsubclassWindow();
     release();
 }
 
 bool Surface::initialize()
 {
+    if (mNativeWindow.getNativeWindow())
+    {
+        if (!mNativeWindow.initialize())
+        {
+            return false;
+        }
+    }
+
     if (!resetSwapChain())
       return false;
 
     return true;
 }
 
 void Surface::release()
 {
@@ -97,17 +107,17 @@ bool Surface::resetSwapChain()
     ASSERT(!mSwapChain);
 
     int width;
     int height;
 
     if (!mFixedSize)
     {
         RECT windowRect;
-        if (!GetClientRect(getWindowHandle(), &windowRect))
+        if (!mNativeWindow.getClientRect(&windowRect))
         {
             ASSERT(false);
 
             ERR("Could not retrieve the window dimensions");
             return error(EGL_BAD_SURFACE, false);
         }
 
         width = windowRect.right - windowRect.left;
@@ -115,17 +125,17 @@ bool Surface::resetSwapChain()
     }
     else
     {
         // non-window surface - size is determined at creation
         width = mWidth;
         height = mHeight;
     }
 
-    mSwapChain = mRenderer->createSwapChain(mWindow, mShareHandle,
+    mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle,
                                             mConfig->mRenderTargetFormat,
                                             mConfig->mDepthStencilFormat);
     if (!mSwapChain)
     {
         return error(EGL_BAD_ALLOC, false);
     }
 
     if (!resetSwapChain(width, height))
@@ -219,19 +229,19 @@ bool Surface::swapRect(EGLint x, EGLint 
         return error(status, false);
     }
 
     checkForOutOfDateSwapChain();
 
     return true;
 }
 
-HWND Surface::getWindowHandle()
+EGLNativeWindowType Surface::getWindowHandle()
 {
-    return mWindow;
+    return mNativeWindow.getNativeWindow();
 }
 
 
 #define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
 #define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
 
 static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
 {
@@ -244,79 +254,86 @@ static LRESULT CALLBACK SurfaceWindowPro
       }
   }
   WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
   return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
 }
 
 void Surface::subclassWindow()
 {
-    if (!mWindow)
+    HWND window = mNativeWindow.getNativeWindow();
+    if (!window)
     {
         return;
     }
 
     DWORD processId;
-    DWORD threadId = GetWindowThreadProcessId(mWindow, &processId);
+    DWORD threadId = GetWindowThreadProcessId(window, &processId);
     if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
     {
         return;
     }
 
     SetLastError(0);
-    LONG_PTR oldWndProc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
+    LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
     if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
     {
         mWindowSubclassed = false;
         return;
     }
 
-    SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
-    SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
+    SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
+    SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
     mWindowSubclassed = true;
 }
 
 void Surface::unsubclassWindow()
 {
     if(!mWindowSubclassed)
     {
         return;
     }
 
+    HWND window = mNativeWindow.getNativeWindow();
+    if (!window)
+    {
+        return;
+    }
+
     // un-subclass
-    LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(mWindow, kParentWndProc));
+    LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, kParentWndProc));
 
     // Check the windowproc is still SurfaceWindowProc.
     // If this assert fails, then it is likely the application has subclassed the
     // hwnd as well and did not unsubclass before destroying its EGL context. The
     // application should be modified to either subclass before initializing the
     // EGL context, or to unsubclass before destroying the EGL context.
     if(parentWndFunc)
     {
-        LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc);
+        LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc);
         UNUSED_ASSERTION_VARIABLE(prevWndFunc);
         ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
     }
 
-    RemoveProp(mWindow, kSurfaceProperty);
-    RemoveProp(mWindow, kParentWndProc);
+    RemoveProp(window, kSurfaceProperty);
+    RemoveProp(window, kParentWndProc);
     mWindowSubclassed = false;
 }
 
 bool Surface::checkForOutOfDateSwapChain()
 {
     RECT client;
     int clientWidth = getWidth();
     int clientHeight = getHeight();
     bool sizeDirty = false;
-    if (!mFixedSize && !IsIconic(getWindowHandle()))
+    if (!mFixedSize && !mNativeWindow.isIconic())
     {
         // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized
         // because that's not a useful size to render to.
-        if (!GetClientRect(getWindowHandle(), &client))
+        if (!mNativeWindow.getClientRect(&client))
         {
             ASSERT(false);
             return false;
         }
 
         // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.
         clientWidth = client.right - client.left;
         clientHeight = client.bottom - client.top;
--- a/gfx/angle/src/libEGL/Surface.h
+++ b/gfx/angle/src/libEGL/Surface.h
@@ -9,16 +9,17 @@
 // Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
 
 #ifndef LIBEGL_SURFACE_H_
 #define LIBEGL_SURFACE_H_
 
 #include <EGL/egl.h>
 
 #include "common/angleutils.h"
+#include "common/NativeWindow.h"
 
 namespace gl
 {
 class Texture2D;
 }
 namespace rx
 {
 class Renderer;
@@ -28,26 +29,26 @@ class SwapChain;
 namespace egl
 {
 class Display;
 class Config;
 
 class Surface
 {
   public:
-    Surface(Display *display, const egl::Config *config, HWND window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported);
+    Surface(Display *display, const egl::Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported);
     Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget);
 
     virtual ~Surface();
 
     bool initialize();
     void release();
     bool resetSwapChain();
 
-    HWND getWindowHandle();
+    EGLNativeWindowType getWindowHandle();
     bool swap();
     bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
 
     virtual EGLint isPostSubBufferSupported() const;
 
     virtual rx::SwapChain *getSwapChain() const;
 
     void setSwapInterval(EGLint interval);
@@ -78,17 +79,17 @@ private:
     rx::SwapChain *mSwapChain;
 
     void subclassWindow();
     void unsubclassWindow();
     bool resizeSwapChain(int backbufferWidth, int backbufferHeight);
     bool resetSwapChain(int backbufferWidth, int backbufferHeight);
     bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
 
-    const HWND mWindow;            // Window that the surface is created for.
+    rx::NativeWindow mNativeWindow;   // Handler for the Window that the surface is created for.
     bool mWindowSubclassed;        // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
     const egl::Config *mConfig;    // EGL config surface was created with
     EGLint mHeight;                // Height of surface
     EGLint mWidth;                 // Width of surface
 //  EGLint horizontalResolution;   // Horizontal dot pitch
 //  EGLint verticalResolution;     // Vertical dot pitch
 //  EGLBoolean largestPBuffer;     // If true, create largest pbuffer possible
 //  EGLBoolean mipmapTexture;      // True if texture has mipmaps
--- a/gfx/angle/src/libEGL/libEGL.cpp
+++ b/gfx/angle/src/libEGL/libEGL.cpp
@@ -14,16 +14,18 @@
 #include "libGLESv2/Texture.h"
 #include "libGLESv2/main.h"
 #include "libGLESv2/renderer/SwapChain.h"
 
 #include "libEGL/main.h"
 #include "libEGL/Display.h"
 #include "libEGL/Surface.h"
 
+#include "common/NativeWindow.h"
+
 bool validateDisplay(egl::Display *display)
 {
     if (display == EGL_NO_DISPLAY)
     {
         return egl::error(EGL_BAD_DISPLAY, false);
     }
 
     if (!display->isInitialized())
@@ -319,24 +321,22 @@ EGLSurface __stdcall eglCreateWindowSurf
 
     egl::Display *display = static_cast<egl::Display*>(dpy);
 
     if (!validateConfig(display, config))
     {
         return EGL_NO_SURFACE;
     }
 
-    HWND window = (HWND)win;
-
-    if (!IsWindow(window))
+    if (!isValidEGLNativeWindowType(win))
     {
         return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
     }
 
-    return display->createWindowSurface(window, config, attrib_list);
+    return display->createWindowSurface(win, config, attrib_list);
 }
 
 EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
 {
     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
           dpy, config, attrib_list);
 
     egl::Display *display = static_cast<egl::Display*>(dpy);
--- a/gfx/angle/src/libEGL/moz.build
+++ b/gfx/angle/src/libEGL/moz.build
@@ -4,16 +4,17 @@
 UNIFIED_SOURCES += [
     '../common/angleutils.cpp',
     '../common/debug.cpp',
     '../common/event_tracer.cpp',
     '../common/mathutil.cpp',
     '../common/RefCountObject.cpp',
     '../common/tls.cpp',
     '../common/utilities.cpp',
+    '../common/win32/NativeWindow.cpp',
     'Config.cpp',
     'Display.cpp',
     'libEGL.cpp',
     'main.cpp',
     'Surface.cpp',
 ]
 
 
@@ -49,13 +50,14 @@ DEFINES['GL_GLEXT_PROTOTYPES'] = ""
 DEFINES['EGLAPI'] = ""
 
 # ANGLE uses the STL, so we can't use our derpy STL wrappers.
 DISABLE_STL_WRAPPING = True
 
 
 LOCAL_INCLUDES += [ '../../include', '../../src' ]
 USE_LIBS += [ 'libGLESv2' ]
+EXTRA_DSO_LDOPTS += [ '../libGLESv2/libGLESv2.lib' ]
 
 SharedLibrary('libEGL')
 
 RCFILE = SRCDIR + '/libEGL.rc'
 DEFFILE = SRCDIR + '/libEGL.def'
--- a/gfx/angle/src/libGLESv2.gypi
+++ b/gfx/angle/src/libGLESv2.gypi
@@ -3,17 +3,17 @@
 # found in the LICENSE file.
 
 {
     'variables':
     {
         'angle_enable_d3d9%': 1,
         'angle_enable_d3d11%': 1,
         # These file lists are shared with the GN build.
-        'angle_libglesv2_sources':
+        'angle_libangle_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',
@@ -31,21 +31,23 @@
             'common/blocklayout.h',
             'common/debug.cpp',
             'common/debug.h',
             'common/event_tracer.cpp',
             'common/event_tracer.h',
             'common/mathutil.cpp',
             'common/mathutil.h',
             'common/platform.h',
+            'common/NativeWindow.h',
             'common/tls.cpp',
             'common/tls.h',
             'common/utilities.cpp',
             'common/utilities.h',
             'common/version.h',
+            'common/win32/NativeWindow.cpp',
             'libGLESv2/BinaryStream.h',
             'libGLESv2/Buffer.cpp',
             'libGLESv2/Buffer.h',
             'libGLESv2/Caps.cpp',
             'libGLESv2/Caps.h',
             'libGLESv2/Constants.h',
             'libGLESv2/Context.cpp',
             'libGLESv2/Context.h',
@@ -55,16 +57,18 @@
             'libGLESv2/Fence.h',
             'libGLESv2/Float16ToFloat32.cpp',
             'libGLESv2/Framebuffer.cpp',
             'libGLESv2/Framebuffer.h',
             'libGLESv2/FramebufferAttachment.cpp',
             'libGLESv2/FramebufferAttachment.h',
             'libGLESv2/HandleAllocator.cpp',
             'libGLESv2/HandleAllocator.h',
+            'libGLESv2/ImageIndex.h',
+            'libGLESv2/ImageIndex.cpp',
             'libGLESv2/Program.cpp',
             'libGLESv2/Program.h',
             'libGLESv2/ProgramBinary.cpp',
             'libGLESv2/ProgramBinary.h',
             'libGLESv2/Query.cpp',
             'libGLESv2/Query.h',
             'libGLESv2/Renderbuffer.cpp',
             'libGLESv2/Renderbuffer.h',
@@ -85,39 +89,38 @@
             'libGLESv2/VertexArray.cpp',
             'libGLESv2/VertexArray.h',
             'libGLESv2/VertexAttribute.cpp',
             'libGLESv2/VertexAttribute.h',
             'libGLESv2/angletypes.cpp',
             'libGLESv2/angletypes.h',
             'libGLESv2/formatutils.cpp',
             'libGLESv2/formatutils.h',
-            'libGLESv2/libGLESv2.cpp',
-            'libGLESv2/libGLESv2.def',
-            'libGLESv2/libGLESv2.rc',
             'libGLESv2/main.cpp',
             'libGLESv2/main.h',
             'libGLESv2/queryconversions.cpp',
             'libGLESv2/queryconversions.h',
             'libGLESv2/renderer/BufferImpl.h',
             'libGLESv2/renderer/FenceImpl.h',
             'libGLESv2/renderer/Image.cpp',
             'libGLESv2/renderer/Image.h',
             'libGLESv2/renderer/IndexRangeCache.cpp',
             'libGLESv2/renderer/IndexRangeCache.h',
+            'libGLESv2/renderer/ProgramImpl.h',
             'libGLESv2/renderer/QueryImpl.h',
             'libGLESv2/renderer/RenderTarget.h',
             'libGLESv2/renderer/Renderer.cpp',
             'libGLESv2/renderer/Renderer.h',
             'libGLESv2/renderer/ShaderExecutable.h',
             'libGLESv2/renderer/ShaderImpl.h',
             'libGLESv2/renderer/SwapChain.h',
             'libGLESv2/renderer/TextureImpl.h',
             'libGLESv2/renderer/TransformFeedbackImpl.h',
             'libGLESv2/renderer/VertexArrayImpl.h',
+            'libGLESv2/renderer/Workarounds.h',
             'libGLESv2/renderer/copyimage.cpp',
             'libGLESv2/renderer/copyimage.h',
             'libGLESv2/renderer/copyimage.inl',
             'libGLESv2/renderer/copyvertex.h',
             'libGLESv2/renderer/copyvertex.inl',
             'libGLESv2/renderer/generatemip.h',
             'libGLESv2/renderer/generatemip.inl',
             'libGLESv2/renderer/imageformats.h',
@@ -149,16 +152,18 @@
             'libGLESv2/renderer/d3d/ImageD3D.cpp',
             'libGLESv2/renderer/d3d/ImageD3D.h',
             'libGLESv2/renderer/d3d/IndexBuffer.cpp',
             'libGLESv2/renderer/d3d/IndexBuffer.h',
             'libGLESv2/renderer/d3d/IndexDataManager.cpp',
             'libGLESv2/renderer/d3d/IndexDataManager.h',
             'libGLESv2/renderer/d3d/MemoryBuffer.cpp',
             'libGLESv2/renderer/d3d/MemoryBuffer.h',
+            'libGLESv2/renderer/d3d/ProgramD3D.cpp',
+            'libGLESv2/renderer/d3d/ProgramD3D.h',
             'libGLESv2/renderer/d3d/ShaderD3D.cpp',
             'libGLESv2/renderer/d3d/ShaderD3D.h',
             'libGLESv2/renderer/d3d/TextureD3D.cpp',
             'libGLESv2/renderer/d3d/TextureD3D.h',
             'libGLESv2/renderer/d3d/TextureStorage.cpp',
             'libGLESv2/renderer/d3d/TextureStorage.h',
             'libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp',
             'libGLESv2/renderer/d3d/TransformFeedbackD3D.h',
@@ -303,37 +308,54 @@
     # anything also change angle/BUILD.gn
     'conditions':
     [
         ['OS=="win"',
         {
             'targets':
             [
                 {
-                    'target_name': 'libGLESv2',
-                    'type': 'shared_library',
+                    'target_name': 'libANGLE',
+                    #TODO(jamdill/geofflang): support shared
+                    'type': 'static_library',
                     'dependencies': [ 'translator', 'commit_id', 'copy_compiler_dll' ],
                     'includes': [ '../build/common_defines.gypi', ],
                     'include_dirs':
                     [
                         '.',
                         '../include',
                         'libGLESv2',
                     ],
                     'sources':
                     [
-                        '<@(angle_libglesv2_sources)',
+                        '<@(angle_libangle_sources)',
                     ],
                     'defines':
                     [
                         'GL_APICALL=',
                         'GL_GLEXT_PROTOTYPES=',
                         'EGLAPI=',
                         'ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ "d3dcompiler_46.dll", "d3dcompiler_43.dll" }',
                     ],
+                    'direct_dependent_settings':
+                    {
+                        'include_dirs':
+                        [
+                            '.',
+                            '../include',
+                            'libGLESv2',
+                        ],
+                        'defines':
+                        [
+                            'GL_APICALL=',
+                            'GL_GLEXT_PROTOTYPES=',
+                            'EGLAPI=',
+                            'ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ "d3dcompiler_46.dll", "d3dcompiler_43.dll" }',
+                        ],
+                    },
                     'conditions':
                     [
                         ['angle_enable_d3d9==1 or angle_enable_d3d11==1',
                         {
                             'sources':
                             [
                                 '<@(angle_d3d_shared_sources)',
                             ],
@@ -343,45 +365,51 @@
                             'sources':
                             [
                                 '<@(angle_d3d9_sources)',
                             ],
                             'defines':
                             [
                                 'ANGLE_ENABLE_D3D9',
                             ],
-                            'msvs_settings':
+                            'link_settings':
                             {
-                                'VCLinkerTool':
+                                'msvs_settings':
                                 {
-                                    'AdditionalDependencies':
-                                    [
-                                        'd3d9.lib',
-                                    ]
-                                }
+                                    'VCLinkerTool':
+                                    {
+                                        'AdditionalDependencies':
+                                        [
+                                            'd3d9.lib',
+                                        ]
+                                    }
+                                },
                             },
                         }],
                         ['angle_enable_d3d11==1',
                         {
                             'sources':
                             [
                                 '<@(angle_d3d11_sources)',
                             ],
                             'defines':
                             [
                                 'ANGLE_ENABLE_D3D11',
                             ],
-                            'msvs_settings':
+                            'link_settings':
                             {
-                                'VCLinkerTool':
+                                'msvs_settings':
                                 {
-                                    'AdditionalDependencies':
-                                    [
-                                        'dxguid.lib',
-                                    ],
+                                    'VCLinkerTool':
+                                    {
+                                        'AdditionalDependencies':
+                                        [
+                                            'dxguid.lib',
+                                        ]
+                                    }
                                 },
                             },
                         }],
                     ],
 
                     'configurations':
                     {
                         'Debug':
@@ -399,39 +427,37 @@
                                         'd3d9.lib',
                                     ]
                                 }
                             },
                         },
                     },
                 },
                 {
-                    # This target supports angle_implementation_unittests.
-                    # It only executes cross-platform code and therefore
-                    # doesn't need any Direct3D DLLs.
+                    'target_name': 'libGLESv2',
+                    'type': 'shared_library',
+                    'dependencies': [ 'libANGLE' ],
+                    'includes': [ '../build/common_defines.gypi', ],
+                    'sources':
+                    [
+                        'libGLESv2/libGLESv2.cpp',
+                        'libGLESv2/libGLESv2.def',
+                        'libGLESv2/libGLESv2.rc',
+                    ],
+                },
+                {
                     'target_name': 'libGLESv2_static',
                     'type': 'static_library',
-                    'dependencies': [ 'translator', 'commit_id' ],
+                    # make sure we depend on commit_id as a hard dependency, otherwise
+                    # we will try to build the static_lib in parallel
+                    'dependencies': [ 'libANGLE', 'commit_id' ],
                     'includes': [ '../build/common_defines.gypi', ],
-                    'include_dirs':
-                    [
-                        '.',
-                        '../include',
-                        'libGLESv2',
-                    ],
                     'sources':
                     [
-                        '<@(angle_libglesv2_sources)',
-                    ],
-                    'defines':
-                    [
-                        'GL_APICALL=',
-                        'GL_GLEXT_PROTOTYPES=',
-                        'EGLAPI=',
-                        # Workaround for D3D-specific code in Renderer.h
-                        'ANGLE_COMPILE_OPTIMIZATION_LEVEL=0',
+                        'libGLESv2/libGLESv2.cpp',
+                        'libGLESv2/libGLESv2.rc',
                     ],
                 },
             ],
         },
         ],
     ],
 }
--- a/gfx/angle/src/libGLESv2/BinaryStream.h
+++ b/gfx/angle/src/libGLESv2/BinaryStream.h
@@ -10,28 +10,29 @@
 #define LIBGLESV2_BINARYSTREAM_H_
 
 #include "common/angleutils.h"
 #include "common/mathutil.h"
 
 #include <cstddef>
 #include <string>
 #include <vector>
+#include <stdint.h>
 
 namespace gl
 {
 
 class BinaryInputStream
 {
   public:
     BinaryInputStream(const void *data, size_t length)
     {
         mError = false;
         mOffset = 0;
-        mData = static_cast<const char*>(data);
+        mData = static_cast<const uint8_t*>(data);
         mLength = length;
     }
 
     // readInt will generate an error for bool types
     template <class IntT>
     IntT readInt()
     {
         int value;
@@ -80,17 +81,17 @@ class BinaryInputStream
         }
 
         if (mOffset + length > mLength)
         {
             mError = true;
             return;
         }
 
-        v->assign(mData + mOffset, length);
+        v->assign(reinterpret_cast<const char *>(mData) + mOffset, length);
         mOffset += length;
     }
 
     void skip(size_t length)
     {
         if (mOffset + length > mLength)
         {
             mError = true;
@@ -110,21 +111,26 @@ class BinaryInputStream
         return mError;
     }
 
     bool endOfStream() const
     {
         return mOffset == mLength;
     }
 
+    const uint8_t *data()
+    {
+        return mData;
+    }
+
   private:
     DISALLOW_COPY_AND_ASSIGN(BinaryInputStream);
     bool mError;
     size_t mOffset;
-    const char *mData;
+    const uint8_t *mData;
     size_t mLength;
 
     template <typename T>
     void read(T *v, size_t num)
     {
         META_ASSERT(std::is_fundamental<T>::value);
 
         size_t length = num * sizeof(T);
--- a/gfx/angle/src/libGLESv2/Buffer.cpp
+++ b/gfx/angle/src/libGLESv2/Buffer.cpp
@@ -28,68 +28,99 @@ Buffer::Buffer(rx::BufferImpl *impl, GLu
 {
 }
 
 Buffer::~Buffer()
 {
     SafeDelete(mBuffer);
 }
 
-void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
+Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
 {
+    gl::Error error = mBuffer->setData(data, size, usage);
+    if (error.isError())
+    {
+        return error;
+    }
+
     mIndexRangeCache.clear();
     mUsage = usage;
     mSize = size;
-    mBuffer->setData(data, size, usage);
+
+    return error;
 }
 
-void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
+Error Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
 {
+    gl::Error error = mBuffer->setSubData(data, size, offset);
+    if (error.isError())
+    {
+        return error;
+    }
+
     mIndexRangeCache.invalidateRange(offset, size);
-    mBuffer->setSubData(data, size, offset);
+
+    return error;
 }
 
-void Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
+Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
 {
+    gl::Error error = mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size);
+    if (error.isError())
+    {
+        return error;
+    }
+
     mIndexRangeCache.invalidateRange(destOffset, size);
-    mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size);
+
+    return error;
 }
 
-GLvoid *Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access)
+Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access)
 {
     ASSERT(!mMapped);
     ASSERT(offset + length <= mSize);
 
-    void *dataPointer = mBuffer->map(offset, length, access);
+    Error error = mBuffer->map(offset, length, access, &mMapPointer);
+    if (error.isError())
+    {
+        mMapPointer = NULL;
+        return error;
+    }
 
     mMapped = GL_TRUE;
-    mMapPointer = static_cast<GLvoid*>(static_cast<GLubyte*>(dataPointer));
     mMapOffset = static_cast<GLint64>(offset);
     mMapLength = static_cast<GLint64>(length);
     mAccessFlags = static_cast<GLint>(access);
 
     if ((access & GL_MAP_WRITE_BIT) > 0)
     {
         mIndexRangeCache.invalidateRange(offset, length);
     }
 
-    return mMapPointer;
+    return error;
 }
 
-void Buffer::unmap()
+Error Buffer::unmap()
 {
     ASSERT(mMapped);
 
-    mBuffer->unmap();
+    Error error = mBuffer->unmap();
+    if (error.isError())
+    {
+        return error;
+    }
 
     mMapped = GL_FALSE;
     mMapPointer = NULL;
     mMapOffset = 0;
     mMapLength = 0;
     mAccessFlags = 0;
+
+    return error;
 }
 
 void Buffer::markTransformFeedbackUsage()
 {
     // TODO: Only used by the DX11 backend. Refactor to a more appropriate place.
     mBuffer->markTransformFeedbackUsage();
     mIndexRangeCache.clear();
 }
--- a/gfx/angle/src/libGLESv2/Buffer.h
+++ b/gfx/angle/src/libGLESv2/Buffer.h
@@ -6,16 +6,18 @@
 
 // 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 LIBGLESV2_BUFFER_H_
 #define LIBGLESV2_BUFFER_H_
 
+#include "libGLESv2/Error.h"
+
 #include "common/angleutils.h"
 #include "common/RefCountObject.h"
 #include "libGLESv2/renderer/IndexRangeCache.h"
 
 namespace rx
 {
 class Renderer;
 class BufferImpl;
@@ -26,23 +28,23 @@ namespace gl
 
 class Buffer : public RefCountObject
 {
   public:
     Buffer(rx::BufferImpl *impl, GLuint id);
 
     virtual ~Buffer();
 
-    void bufferData(const void *data, GLsizeiptr size, GLenum usage);
-    void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
-    void copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
-    GLvoid *mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access);
-    void unmap();
+    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 mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access);
+    Error unmap();
 
-    GLenum  getUsage() const { return mUsage; }
+    GLenum getUsage() const { return mUsage; }
     GLint getAccessFlags() const {  return mAccessFlags; }
     GLboolean isMapped() const { return mMapped; }
     GLvoid *getMapPointer() const { return mMapPointer; }
     GLint64 getMapOffset() const { return mMapOffset; }
     GLint64 getMapLength() const { return mMapLength; }
     GLint64 getSize() const { return mSize; }
 
     rx::BufferImpl *getImplementation() const { return mBuffer; }
--- a/gfx/angle/src/libGLESv2/Caps.cpp
+++ b/gfx/angle/src/libGLESv2/Caps.cpp
@@ -177,22 +177,27 @@ std::vector<std::string> Extensions::get
     InsertExtensionString("GL_ANGLE_texture_usage",            textureUsage,             &extensionStrings);
     InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource,   &extensionStrings);
     InsertExtensionString("GL_EXT_color_buffer_float",         colorBufferFloat,         &extensionStrings);
 
     return extensionStrings;
 }
 
 static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vector<GLenum> &requiredFormats,
-                             bool requiresFiltering, bool requiresRendering)
+                             bool requiresTexturing, bool requiresFiltering, bool requiresRendering)
 {
     for (size_t i = 0; i < requiredFormats.size(); i++)
     {
         const TextureCaps &cap = textureCaps.get(requiredFormats[i]);
 
+        if (requiresTexturing && !cap.texturable)
+        {
+            return false;
+        }
+
         if (requiresFiltering && !cap.filterable)
         {
             return false;
         }
 
         if (requiresRendering && !cap.renderable)
         {
             return false;
@@ -204,66 +209,66 @@ static bool GetFormatSupport(const Textu
 
 // Checks for GL_OES_rgb8_rgba8 support
 static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_RGB8);
     requiredFormats.push_back(GL_RGBA8);
 
-    return GetFormatSupport(textureCaps, requiredFormats, true, true);
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
 }
 
 // Checks for GL_EXT_texture_format_BGRA8888 support
 static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_BGRA8_EXT);
 
-    return GetFormatSupport(textureCaps, requiredFormats, true, true);
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, 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, false, true);
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
 }
 
 // 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, false);
+    return 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);
 
-    return GetFormatSupport(textureCaps, requiredFormats, false, true);
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
 }
 
 // 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, false);
+    return 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);
@@ -273,85 +278,85 @@ static bool DetermineRGTextureSupport(co
         requiredFormats.push_back(GL_RG16F);
     }
     if (checkFloatFormats)
     {
         requiredFormats.push_back(GL_R32F);
         requiredFormats.push_back(GL_RG32F);
     }
 
-    return GetFormatSupport(textureCaps, requiredFormats, true, false);
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
 }
 
 // Check for GL_EXT_texture_compression_dxt1
 static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
     requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
 
-    return GetFormatSupport(textureCaps, requiredFormats, true, false);
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
 }
 
 // Check for GL_ANGLE_texture_compression_dxt3
 static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
 
-    return GetFormatSupport(textureCaps, requiredFormats, true, false);
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
 }
 
 // Check for GL_ANGLE_texture_compression_dxt5
 static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
 
-    return GetFormatSupport(textureCaps, requiredFormats, true, false);
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
 }
 
 // Check for GL_ANGLE_texture_compression_dxt5
 static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFilterFormats;
     requiredFilterFormats.push_back(GL_SRGB8);
     requiredFilterFormats.push_back(GL_SRGB8_ALPHA8);
 
     std::vector<GLenum> requiredRenderFormats;
     requiredRenderFormats.push_back(GL_SRGB8_ALPHA8);
 
-    return GetFormatSupport(textureCaps, requiredFilterFormats, true, false) &&
-           GetFormatSupport(textureCaps, requiredRenderFormats, false, true);
+    return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false) &&
+           GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true);
 }
 
 // Check for GL_ANGLE_depth_texture
 static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_DEPTH_COMPONENT16);
     requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES);
     requiredFormats.push_back(GL_DEPTH24_STENCIL8_OES);
 
-    return GetFormatSupport(textureCaps, requiredFormats, true, true);
+    return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
 }
 
 // Check for GL_EXT_color_buffer_float
 static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps)
 {
     std::vector<GLenum> requiredFormats;
     requiredFormats.push_back(GL_R16F);
     requiredFormats.push_back(GL_RG16F);
     requiredFormats.push_back(GL_RGBA16F);
     requiredFormats.push_back(GL_R32F);
     requiredFormats.push_back(GL_RG32F);
     requiredFormats.push_back(GL_RGBA32F);
     requiredFormats.push_back(GL_R11F_G11F_B10F);
 
-    return GetFormatSupport(textureCaps, requiredFormats, false, true);
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
 }
 
 void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
 {
     rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps);
     textureFormatBGRA8888 = DetermineBGRA8TextureSupport(textureCaps);
     textureHalfFloat = DetermineHalfFloatTextureSupport(textureCaps);
     textureHalfFloatLinear = DetermineHalfFloatTextureFilteringSupport(textureCaps);
--- a/gfx/angle/src/libGLESv2/Constants.h
+++ b/gfx/angle/src/libGLESv2/Constants.h
@@ -10,22 +10,18 @@
 #define LIBGLESV2_CONSTANTS_H_
 
 namespace gl
 {
 
 enum
 {
     MAX_VERTEX_ATTRIBS = 16,
-    MAX_TEXTURE_IMAGE_UNITS = 16,
 
     // Implementation upper limits, real maximums depend on the hardware
-    IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 16,
-    IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS = MAX_TEXTURE_IMAGE_UNITS + IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS,    
-
     IMPLEMENTATION_MAX_VARYING_VECTORS = 32,
     IMPLEMENTATION_MAX_DRAW_BUFFERS = 8,
     IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS = IMPLEMENTATION_MAX_DRAW_BUFFERS + 2, // 2 extra for depth and/or stencil buffers
 
     IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS = 16,
     IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS = 16,
     IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS = IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS +
                                                          IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS,
--- a/gfx/angle/src/libGLESv2/Context.cpp
+++ b/gfx/angle/src/libGLESv2/Context.cpp
@@ -39,16 +39,17 @@ namespace gl
 {
 
 Context::Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
     : mRenderer(renderer)
 {
     ASSERT(robustAccess == false);   // Unimplemented
 
     initCaps(clientVersion);
+    mState.initialize(mCaps, clientVersion);
 
     mClientVersion = clientVersion;
 
     mFenceNVHandleAllocator.setBaseHandle(0);
 
     if (shareContext != NULL)
     {
         mResourceManager = shareContext->mResourceManager;
@@ -60,26 +61,36 @@ Context::Context(int clientVersion, cons
     }
 
     // [OpenGL ES 2.0.24] section 3.7 page 83:
     // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
     // and cube map texture state vectors respectively associated with them.
     // In order that access to these initial textures not be lost, they are treated as texture
     // objects all of whose names are 0.
 
-    mTexture2DZero.set(new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0));
-    mTextureCubeMapZero.set(new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0));
-    mTexture3DZero.set(new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0));
-    mTexture2DArrayZero.set(new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0));
+    mZeroTextures[GL_TEXTURE_2D].set(new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0));
+    bindTexture(GL_TEXTURE_2D, 0);
+
+    mZeroTextures[GL_TEXTURE_CUBE_MAP].set(new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0));
+    bindTexture(GL_TEXTURE_CUBE_MAP, 0);
+
+    if (mClientVersion >= 3)
+    {
+        // TODO: These could also be enabled via extension
+        mZeroTextures[GL_TEXTURE_3D].set(new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0));
+        bindTexture(GL_TEXTURE_3D, 0);
+
+        mZeroTextures[GL_TEXTURE_2D_ARRAY].set(new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0));
+        bindTexture(GL_TEXTURE_2D_ARRAY, 0);
+    }
 
     bindVertexArray(0);
     bindArrayBuffer(0);
     bindElementArrayBuffer(0);
-    bindTextureCubeMap(0);
-    bindTexture2D(0);
+
     bindReadFramebuffer(0);
     bindDrawFramebuffer(0);
     bindRenderbuffer(0);
 
     bindGenericUniformBuffer(0);
     for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++)
     {
         bindIndexedUniformBuffer(0, i, 0, -1);
@@ -147,25 +158,27 @@ Context::~Context()
     }
 
     mTransformFeedbackZero.set(NULL);
     while (!mTransformFeedbackMap.empty())
     {
         deleteTransformFeedback(mTransformFeedbackMap.begin()->first);
     }
 
-    for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
+    for (TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); i++)
     {
-        mIncompleteTextures[type].set(NULL);
+        i->second.set(NULL);
     }
+    mIncompleteTextures.clear();
 
-    mTexture2DZero.set(NULL);
-    mTextureCubeMapZero.set(NULL);
-    mTexture3DZero.set(NULL);
-    mTexture2DArrayZero.set(NULL);
+    for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++)
+    {
+        i->second.set(NULL);
+    }
+    mZeroTextures.clear();
 
     mResourceManager->release();
 }
 
 void Context::makeCurrent(egl::Surface *surface)
 {
     if (!mHasBeenCurrent)
     {
@@ -497,42 +510,21 @@ void Context::bindArrayBuffer(unsigned i
 
 void Context::bindElementArrayBuffer(unsigned int buffer)
 {
     mResourceManager->checkBufferAllocation(buffer);
 
     mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer));
 }
 
-void Context::bindTexture2D(GLuint texture)
+void Context::bindTexture(GLenum target, GLuint texture)
 {
-    mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
-
-    mState.setSamplerTexture(TEXTURE_2D, getTexture(texture));
-}
-
-void Context::bindTextureCubeMap(GLuint texture)
-{
-    mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);
+    mResourceManager->checkTextureAllocation(texture, target);
 
-    mState.setSamplerTexture(TEXTURE_CUBE, getTexture(texture));
-}
-
-void Context::bindTexture3D(GLuint texture)
-{
-    mResourceManager->checkTextureAllocation(texture, TEXTURE_3D);
-
-    mState.setSamplerTexture(TEXTURE_3D, getTexture(texture));
-}
-
-void Context::bindTexture2DArray(GLuint texture)
-{
-    mResourceManager->checkTextureAllocation(texture, TEXTURE_2D_ARRAY);
-
-    mState.setSamplerTexture(TEXTURE_2D_ARRAY, getTexture(texture));
+    mState.setSamplerTexture(target, getTexture(texture));
 }
 
 void Context::bindReadFramebuffer(GLuint framebuffer)
 {
     if (!getFramebuffer(framebuffer))
     {
         mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer);
     }
@@ -565,17 +557,17 @@ void Context::bindVertexArray(GLuint ver
         mVertexArrayMap[vertexArray] = vertexArrayObject;
     }
 
     mState.setVertexArrayBinding(getVertexArray(vertexArray));
 }
 
 void Context::bindSampler(GLuint textureUnit, GLuint sampler)
 {
-    ASSERT(textureUnit < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS); // TODO: Update for backend-determined array size
+    ASSERT(textureUnit < mCaps.maxCombinedTextureImageUnits);
     mResourceManager->checkSamplerAllocation(sampler);
 
     mState.setSamplerBinding(textureUnit, getSampler(sampler));
 }
 
 void Context::bindGenericUniformBuffer(GLuint buffer)
 {
     mResourceManager->checkBufferAllocation(buffer);
@@ -677,36 +669,45 @@ void Context::setProgramBinary(GLuint pr
 
 }
 
 void Context::bindTransformFeedback(GLuint transformFeedback)
 {
     mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback));
 }
 
-void Context::beginQuery(GLenum target, GLuint query)
+Error Context::beginQuery(GLenum target, GLuint query)
 {
     Query *queryObject = getQuery(query, true, target);
     ASSERT(queryObject);
 
-    // set query as active for specified target
+    // begin query
+    Error error = queryObject->begin();
+    if (error.isError())
+    {
+        return error;
+    }
+
+    // set query as active for specified target only if begin succeeded
     mState.setActiveQuery(target, queryObject);
 
-    // begin query
-    queryObject->begin();
+    return Error(GL_NO_ERROR);
 }
 
-void Context::endQuery(GLenum target)
+Error Context::endQuery(GLenum target)
 {
     Query *queryObject = mState.getActiveQuery(target);
     ASSERT(queryObject);
 
-    queryObject->end();
+    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;
 }
 
 void Context::setFramebufferZero(Framebuffer *buffer)
 {
     // First, check to see if the old default framebuffer
     // was set for draw or read framebuffer, and change
     // the bindings to point to the new one before deleting it.
     if (mState.getDrawFramebuffer()->id() == 0)
@@ -811,46 +812,39 @@ Texture *Context::getTargetTexture(GLenu
       case GL_TEXTURE_3D:       return getTexture3D();
       case GL_TEXTURE_2D_ARRAY: return getTexture2DArray();
       default:                  return NULL;
     }
 }
 
 Texture2D *Context::getTexture2D() const
 {
-    return static_cast<Texture2D*>(getSamplerTexture(mState.getActiveSampler(), TEXTURE_2D));
+    return static_cast<Texture2D*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D));
 }
 
 TextureCubeMap *Context::getTextureCubeMap() const
 {
-    return static_cast<TextureCubeMap*>(getSamplerTexture(mState.getActiveSampler(), TEXTURE_CUBE));
+    return static_cast<TextureCubeMap*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_CUBE_MAP));
 }
 
 Texture3D *Context::getTexture3D() const
 {
-    return static_cast<Texture3D*>(getSamplerTexture(mState.getActiveSampler(), TEXTURE_3D));
+    return static_cast<Texture3D*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_3D));
 }
 
 Texture2DArray *Context::getTexture2DArray() const
 {
-    return static_cast<Texture2DArray*>(getSamplerTexture(mState.getActiveSampler(), TEXTURE_2D_ARRAY));
+    return static_cast<Texture2DArray*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D_ARRAY));
 }
 
-Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) const
+Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const
 {
     if (mState.getSamplerTextureId(sampler, type) == 0)
     {
-        switch (type)
-        {
-          default: UNREACHABLE();
-          case TEXTURE_2D:       return mTexture2DZero.get();
-          case TEXTURE_CUBE:     return mTextureCubeMapZero.get();
-          case TEXTURE_3D:       return mTexture3DZero.get();
-          case TEXTURE_2D_ARRAY: return mTexture2DArrayZero.get();
-        }
+        return mZeroTextures.at(type).get();
     }
     else
     {
         return mState.getSamplerTexture(sampler, type);
     }
 }
 
 void Context::getBooleanv(GLenum pname, GLboolean *params)
@@ -1312,57 +1306,61 @@ bool Context::getIndexedQueryParameterIn
         }
     }
 
     return false;
 }
 
 // Applies the render target surface, depth stencil surface, viewport rectangle and
 // scissor rectangle to the renderer
-bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport)
+Error Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport)
 {
     Framebuffer *framebufferObject = mState.getDrawFramebuffer();
     ASSERT(framebufferObject && framebufferObject->completeness() == GL_FRAMEBUFFER_COMPLETE);
 
-    mRenderer->applyRenderTarget(framebufferObject);
+    gl::Error error = mRenderer->applyRenderTarget(framebufferObject);
+    if (error.isError())
+    {
+        return error;
+    }
 
     float nearZ, farZ;
     mState.getDepthRange(&nearZ, &farZ);
-    if (!mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace,
-                                ignoreViewport))
-    {
-        return false;
-    }
+    mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace,
+                           ignoreViewport);
 
     mRenderer->setScissorRectangle(mState.getScissor(), mState.isScissorTestEnabled());
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
 // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
-void Context::applyState(GLenum drawMode)
+Error Context::applyState(GLenum drawMode)
 {
     Framebuffer *framebufferObject = mState.getDrawFramebuffer();
     int samples = framebufferObject->getSamples();
 
     RasterizerState rasterizer = mState.getRasterizerState();
     rasterizer.pointDrawMode = (drawMode == GL_POINTS);
     rasterizer.multiSample = (samples != 0);
 
-    mRenderer->setRasterizerState(rasterizer);
+    Error error = mRenderer->setRasterizerState(rasterizer);
+    if (error.isError())
+    {
+        return error;
+    }
 
     unsigned int mask = 0;
     if (mState.isSampleCoverageEnabled())
     {
         GLclampf coverageValue;
         bool coverageInvert = false;
         mState.getSampleCoverageParams(&coverageValue, &coverageInvert);
         if (coverageValue != 0)
         {
-
             float threshold = 0.5f;
 
             for (int i = 0; i < samples; ++i)
             {
                 mask <<= 1;
 
                 if ((i + 1) * coverageValue >= threshold)
                 {
@@ -1376,134 +1374,204 @@ void Context::applyState(GLenum drawMode
         {
             mask = ~mask;
         }
     }
     else
     {
         mask = 0xFFFFFFFF;
     }
-    mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask);
+    error = mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(),
-                                    rasterizer.frontFace == GL_CCW);
+    error = mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(),
+                                            rasterizer.frontFace == GL_CCW);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return Error(GL_NO_ERROR);
 }
 
 // Applies the shaders and shader constants to the Direct3D 9 device
-void Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive)
+Error Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive)
 {
     const VertexAttribute *vertexAttributes = mState.getVertexArray()->getVertexAttributes();
 
-    VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS];
+    VertexFormat inputLayout[MAX_VERTEX_ATTRIBS];
     VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.getVertexAttribCurrentValues());
 
     const Framebuffer *fbo = mState.getDrawFramebuffer();
 
-    mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive);
+    Error error = mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    programBinary->applyUniforms();
+    return programBinary->applyUniforms();
 }
 
-size_t Context::getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, SamplerType type, Texture **outTextures,
-                                                   TextureType *outTextureTypes, SamplerState *outSamplers)
+Error Context::generateSwizzles(ProgramBinary *programBinary, SamplerType type)
 {
     size_t samplerRange = programBinary->getUsedSamplerRange(type);
+
     for (size_t i = 0; i < samplerRange; i++)
     {
-        outTextureTypes[i] = programBinary->getSamplerTextureType(type, i);
-        GLint textureUnit = programBinary->getSamplerMapping(type, i, getCaps());   // OpenGL texture image unit index
+        GLenum textureType = programBinary->getSamplerTextureType(type, i);
+        GLint textureUnit = programBinary->getSamplerMapping(type, i, getCaps());
         if (textureUnit != -1)
         {
-            outTextures[i] = getSamplerTexture(textureUnit, outTextureTypes[i]);
-            outTextures[i]->getSamplerStateWithNativeOffset(&outSamplers[i]);
-            Sampler *samplerObject = mState.getSampler(textureUnit);
-            if (samplerObject)
+            Texture* texture = getSamplerTexture(textureUnit, textureType);
+            if (texture->getSamplerState().swizzleRequired())
             {
-                samplerObject->getState(&outSamplers[i]);
+                Error error = mRenderer->generateSwizzle(texture);
+                if (error.isError())
+                {
+                    return error;
+                }
             }
         }
-        else
-        {
-            outTextures[i] = NULL;
-        }
     }
 
-    return samplerRange;
+    return Error(GL_NO_ERROR);
 }
 
-void Context::generateSwizzles(Texture *textures[], size_t count)
+Error Context::generateSwizzles(ProgramBinary *programBinary)
 {
-    for (size_t i = 0; i < count; i++)
+    Error error = generateSwizzles(programBinary, SAMPLER_VERTEX);
+    if (error.isError())
     {
-        if (textures[i] && textures[i]->getSamplerState().swizzleRequired())
-        {
-            mRenderer->generateSwizzle(textures[i]);
-        }
+        return error;
     }
+
+    error = generateSwizzles(programBinary, SAMPLER_PIXEL);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return Error(GL_NO_ERROR);
 }
 
 // For each Direct3D sampler of either the pixel or vertex stage,
 // looks up the corresponding OpenGL texture image unit and texture type,
 // and sets the texture and its addressing/filtering state (or NULL when inactive).
-void Context::applyTextures(SamplerType shaderType, Texture *textures[], TextureType *textureTypes, SamplerState *samplers,
-                            size_t textureCount, const FramebufferTextureSerialArray& framebufferSerials,
-                            size_t framebufferSerialCount)
+Error Context::applyTextures(ProgramBinary *programBinary, SamplerType shaderType,
+                             const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount)
 {
-    // Range of Direct3D samplers of given sampler type
-    size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? mCaps.maxTextureImageUnits
-                                                        : mCaps.maxVertexTextureImageUnits;
+    size_t samplerRange = programBinary->getUsedSamplerRange(shaderType);
+    for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
+    {
+        GLenum textureType = programBinary->getSamplerTextureType(shaderType, samplerIndex);
+        GLint textureUnit = programBinary->getSamplerMapping(shaderType, samplerIndex, getCaps());
+        if (textureUnit != -1)
+        {
+            SamplerState sampler;
+            Texture* texture = getSamplerTexture(textureUnit, textureType);
+            texture->getSamplerStateWithNativeOffset(&sampler);
 
-    for (size_t samplerIndex = 0; samplerIndex < textureCount; samplerIndex++)
-    {
-        Texture *texture = textures[samplerIndex];
-        const SamplerState &sampler = samplers[samplerIndex];
-        TextureType textureType = textureTypes[samplerIndex];
+            Sampler *samplerObject = mState.getSampler(textureUnit);
+            if (samplerObject)
+            {
+                samplerObject->getState(&sampler);
+            }
 
-        if (texture)
-        {
             // TODO: std::binary_search may become unavailable using older versions of GCC
             if (texture->isSamplerComplete(sampler, mTextureCaps, mExtensions, mClientVersion) &&
                 !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial()))
             {
-                mRenderer->setSamplerState(shaderType, samplerIndex, sampler);
-                mRenderer->setTexture(shaderType, samplerIndex, texture);
+                Error error = mRenderer->setSamplerState(shaderType, samplerIndex, sampler);
+                if (error.isError())
+                {
+                    return error;
+                }
+
+                error = mRenderer->setTexture(shaderType, samplerIndex, texture);
+                if (error.isError())
+                {
+                    return error;
+                }
             }
             else
             {
+                // Texture is not sampler complete or it is in use by the framebuffer.  Bind the incomplete texture.
                 Texture *incompleteTexture = getIncompleteTexture(textureType);
-                mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture);
+                gl::Error error = mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture);
+                if (error.isError())
+                {
+                    return error;
+                }
             }
         }
         else
         {
-            mRenderer->setTexture(shaderType, samplerIndex, NULL);
+            // No texture bound to this slot even though it is used by the shader, bind a NULL texture
+            Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL);
+            if (error.isError())
+            {
+                return error;
+            }
+        }
+    }
+
+    // Set all the remaining textures to NULL
+    size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? mCaps.maxTextureImageUnits
+                                                        : mCaps.maxVertexTextureImageUnits;
+    for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
+    {
+        Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL);
+        if (error.isError())
+        {
+            return error;
         }
     }
 
-    for (size_t samplerIndex = textureCount; samplerIndex < samplerCount; samplerIndex++)
-    {
-        mRenderer->setTexture(shaderType, samplerIndex, NULL);
-    }
+    return Error(GL_NO_ERROR);
 }
 
-bool Context::applyUniformBuffers()
+Error Context::applyTextures(ProgramBinary *programBinary)
+{
+    FramebufferTextureSerialArray framebufferSerials;
+    size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&framebufferSerials);
+
+    Error error = applyTextures(programBinary, SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    error = applyTextures(programBinary, SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    return Error(GL_NO_ERROR);
+}
+
+Error Context::applyUniformBuffers()
 {
     Program *programObject = getProgram(mState.getCurrentProgramId());
     ProgramBinary *programBinary = programObject->getProgramBinary();
 
-    std::vector<gl::Buffer*> boundBuffers;
+    std::vector<Buffer*> boundBuffers;
 
     for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++)
     {
         GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex);
 
         if (mState.getIndexedUniformBuffer(blockBinding)->id() == 0)
         {
             // undefined behaviour
-            return false;
+            return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer.");
         }
         else
         {
             Buffer *uniformBuffer = mState.getIndexedUniformBuffer(blockBinding);
             ASSERT(uniformBuffer);
             boundBuffers.push_back(uniformBuffer);
         }
     }
@@ -1539,38 +1607,35 @@ void Context::markTransformFeedbackUsage
         Buffer *buffer = mState.getIndexedTransformFeedbackBuffer(i);
         if (buffer)
         {
             buffer->markTransformFeedbackUsage();
         }
     }
 }
 
-void Context::clear(GLbitfield mask)
+Error Context::clear(GLbitfield mask)
 {
     if (mState.isRasterizerDiscardEnabled())
     {
-        return;
+        return Error(GL_NO_ERROR);
     }
 
     ClearParameters clearParams = mState.getClearParameters(mask);
 
-    if (!applyRenderTarget(GL_TRIANGLES, true))   // Clips the clear to the scissor rectangle but not the viewport
-    {
-        return;
-    }
+    applyRenderTarget(GL_TRIANGLES, true);   // Clips the clear to the scissor rectangle but not the viewport
 
-    mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+    return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
 }
 
-void Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values)
+Error Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values)
 {
     if (mState.isRasterizerDiscardEnabled())
     {
-        return;
+        return Error(GL_NO_ERROR);
     }
 
     // glClearBufferfv can be called to clear the color buffer or depth buffer
     ClearParameters clearParams = mState.getClearParameters(0);
 
     if (buffer == GL_COLOR)
     {
         for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
@@ -1582,53 +1647,47 @@ void Context::clearBufferfv(GLenum buffe
     }
 
     if (buffer == GL_DEPTH)
     {
         clearParams.clearDepth = true;
         clearParams.depthClearValue = values[0];
     }
 
-    if (!applyRenderTarget(GL_TRIANGLES, true))   // Clips the clear to the scissor rectangle but not the viewport
-    {
-        return;
-    }
+    applyRenderTarget(GL_TRIANGLES, true);   // Clips the clear to the scissor rectangle but not the viewport
 
-    mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+    return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
 }
 
-void Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values)
+Error Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values)
 {
     if (mState.isRasterizerDiscardEnabled())
     {
-        return;
+        return Error(GL_NO_ERROR);
     }
 
     // glClearBufferuv can only be called to clear a color buffer
     ClearParameters clearParams = mState.getClearParameters(0);
     for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
     {
         clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
     }
     clearParams.colorUIClearValue = ColorUI(values[0], values[1], values[2], values[3]);
     clearParams.colorClearType = GL_UNSIGNED_INT;
 
-    if (!applyRenderTarget(GL_TRIANGLES, true))   // Clips the clear to the scissor rectangle but not the viewport
-    {
-        return;
-    }
+    applyRenderTarget(GL_TRIANGLES, true);   // Clips the clear to the scissor rectangle but not the viewport
 
-    mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+    return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
 }
 
-void Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values)
+Error Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values)
 {
     if (mState.isRasterizerDiscardEnabled())
     {
-        return;
+        return Error(GL_NO_ERROR);
     }
 
     // glClearBufferfv can be called to clear the color buffer or stencil buffer
     ClearParameters clearParams = mState.getClearParameters(0);
 
     if (buffer == GL_COLOR)
     {
         for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
@@ -1640,197 +1699,209 @@ void Context::clearBufferiv(GLenum buffe
     }
 
     if (buffer == GL_STENCIL)
     {
         clearParams.clearStencil = true;
         clearParams.stencilClearValue = values[1];
     }
 
-    if (!applyRenderTarget(GL_TRIANGLES, true))   // Clips the clear to the scissor rectangle but not the viewport
-    {
-        return;
-    }
+    applyRenderTarget(GL_TRIANGLES, true);   // Clips the clear to the scissor rectangle but not the viewport
 
-    mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+    return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
 }
 
-void Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil)
+Error Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil)
 {
     if (mState.isRasterizerDiscardEnabled())
     {
-        return;
+        return Error(GL_NO_ERROR);
     }
 
     // glClearBufferfi can only be called to clear a depth stencil buffer
     ClearParameters clearParams = mState.getClearParameters(0);
     clearParams.clearDepth = true;
     clearParams.depthClearValue = depth;
     clearParams.clearStencil = true;
     clearParams.stencilClearValue = stencil;
 
-    if (!applyRenderTarget(GL_TRIANGLES, true))   // Clips the clear to the scissor rectangle but not the viewport
-    {
-        return;
-    }
+    applyRenderTarget(GL_TRIANGLES, true);   // Clips the clear to the scissor rectangle but not the viewport
 
-    mRenderer->clear(clearParams, mState.getDrawFramebuffer());
+    return mRenderer->clear(clearParams, mState.getDrawFramebuffer());
 }
 
-void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
-                         GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
+Error Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+                          GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
 {
-    gl::Framebuffer *framebuffer = mState.getReadFramebuffer();
+    Framebuffer *framebuffer = mState.getReadFramebuffer();
 
     GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
     const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat);
     GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, mState.getPackAlignment());
 
-    mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(),
-                          reinterpret_cast<uint8_t*>(pixels));
+    return mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(),
+                                 reinterpret_cast<uint8_t*>(pixels));
 }
 
-void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
+Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
 {
     ASSERT(mState.getCurrentProgramId() != 0);
 
     ProgramBinary *programBinary = mState.getCurrentProgramBinary();
     programBinary->updateSamplerMapping();
 
-    Texture *vsTextures[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-    TextureType vsTextureTypes[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-    SamplerState vsSamplers[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-    size_t vsTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers);
-
-    Texture *psTextures[MAX_TEXTURE_IMAGE_UNITS];
-    TextureType psTextureTypes[MAX_TEXTURE_IMAGE_UNITS];
-    SamplerState psSamplers[MAX_TEXTURE_IMAGE_UNITS];
-    size_t psTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers);
-
-    generateSwizzles(vsTextures, vsTextureCount);
-    generateSwizzles(psTextures, psTextureCount);
+    Error error = generateSwizzles(programBinary);
+    if (error.isError())
+    {
+        return error;
+    }
 
     if (!mRenderer->applyPrimitiveType(mode, count))
     {
-        return;
+        return Error(GL_NO_ERROR);
+    }
+
+    error = applyRenderTarget(mode, false);
+    if (error.isError())
+    {
+        return error;
     }
 
-    if (!applyRenderTarget(mode, false))
+    error = applyState(mode);
+    if (error.isError())
     {
-        return;
+        return error;
     }
 
-    applyState(mode);
-
-    GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances);
-    if (err != GL_NO_ERROR)
+    error = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances);
+    if (error.isError())
     {
-        return gl::error(err);
+        return error;
     }
 
     bool transformFeedbackActive = applyTransformFeedbackBuffers();
 
-    applyShaders(programBinary, transformFeedbackActive);
-
-    FramebufferTextureSerialArray frameBufferSerials;
-    size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&frameBufferSerials);
+    error = applyShaders(programBinary, transformFeedbackActive);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    applyTextures(SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers, vsTextureCount, frameBufferSerials, framebufferSerialCount);
-    applyTextures(SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers, psTextureCount, frameBufferSerials, framebufferSerialCount);
+    error = applyTextures(programBinary);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    if (!applyUniformBuffers())
+    error = applyUniformBuffers();
+    if (error.isError())
     {
-        return;
+        return error;
     }
 
     if (!skipDraw(mode))
     {
-        mRenderer->drawArrays(mode, count, instances, transformFeedbackActive);
+        error = mRenderer->drawArrays(mode, count, instances, transformFeedbackActive);
+        if (error.isError())
+        {
+            return error;
+        }
 
         if (transformFeedbackActive)
         {
             markTransformFeedbackUsage();
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Context::drawElements(GLenum mode, GLsizei count, GLenum type,
-                           const GLvoid *indices, GLsizei instances,
-                           const rx::RangeUI &indexRange)
+Error Context::drawElements(GLenum mode, GLsizei count, GLenum type,
+                            const GLvoid *indices, GLsizei instances,
+                            const rx::RangeUI &indexRange)
 {
     ASSERT(mState.getCurrentProgramId() != 0);
 
     ProgramBinary *programBinary = mState.getCurrentProgramBinary();
     programBinary->updateSamplerMapping();
 
-    Texture *vsTextures[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-    TextureType vsTextureTypes[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-    SamplerState vsSamplers[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
-    size_t vsTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers);
-
-    Texture *psTextures[MAX_TEXTURE_IMAGE_UNITS];
-    TextureType psTextureTypes[MAX_TEXTURE_IMAGE_UNITS];
-    SamplerState psSamplers[MAX_TEXTURE_IMAGE_UNITS];
-    size_t psTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers);
-
-    generateSwizzles(vsTextures, vsTextureCount);
-    generateSwizzles(psTextures, psTextureCount);
+    Error error = generateSwizzles(programBinary);
+    if (error.isError())
+    {
+        return error;
+    }
 
     if (!mRenderer->applyPrimitiveType(mode, count))
     {
-        return;
+        return Error(GL_NO_ERROR);
     }
 
-    if (!applyRenderTarget(mode, false))
+    error = applyRenderTarget(mode, false);
+    if (error.isError())
     {
-        return;
+        return error;
     }
 
-    applyState(mode);
+    error = applyState(mode);
+    if (error.isError())
+    {
+        return error;
+    }
 
     VertexArray *vao = mState.getVertexArray();
     rx::TranslatedIndexData indexInfo;
     indexInfo.indexRange = indexRange;
-    GLenum err = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo);
-    if (err != GL_NO_ERROR)
+    error = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo);
+    if (error.isError())
     {
-        return gl::error(err);
+        return error;
     }
 
     GLsizei vertexCount = indexInfo.indexRange.length() + 1;
-    err = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(),
-                                       mState.getVertexAttribCurrentValues(),
-                                       indexInfo.indexRange.start, vertexCount, instances);
-    if (err != GL_NO_ERROR)
+    error = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(),
+                                         mState.getVertexAttribCurrentValues(),
+                                         indexInfo.indexRange.start, vertexCount, instances);
+    if (error.isError())
     {
-        return gl::error(err);
+        return error;
     }
 
     bool transformFeedbackActive = applyTransformFeedbackBuffers();
     // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation
     // layer.
     ASSERT(!transformFeedbackActive);
 
-    applyShaders(programBinary, transformFeedbackActive);
-
-    FramebufferTextureSerialArray frameBufferSerials;
-    size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&frameBufferSerials);
+    error = applyShaders(programBinary, transformFeedbackActive);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    applyTextures(SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers, vsTextureCount, frameBufferSerials, framebufferSerialCount);
-    applyTextures(SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers, psTextureCount, frameBufferSerials, framebufferSerialCount);
+    error = applyTextures(programBinary);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    if (!applyUniformBuffers())
+    error = applyUniformBuffers();
+    if (error.isError())
     {
-        return;
+        return error;
     }
 
     if (!skipDraw(mode))
     {
-        mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances);
+        error = mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances);
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    return Error(GL_NO_ERROR);
 }
 
 // Implements glFlush when block is false, glFinish when block is true
 void Context::sync(bool block)
 {
     mRenderer->sync(block);
 }
 
@@ -1996,77 +2067,76 @@ void Context::detachTransformFeedback(GL
     mState.detachTransformFeedback(transformFeedback);
 }
 
 void Context::detachSampler(GLuint sampler)
 {
     mState.detachSampler(sampler);
 }
 
-Texture *Context::getIncompleteTexture(TextureType type)
+Texture *Context::getIncompleteTexture(GLenum type)
 {
-    Texture *t = mIncompleteTextures[type].get();
-
-    if (t == NULL)
+    if (mIncompleteTextures.find(type) == mIncompleteTextures.end())
     {
         const GLubyte color[] = { 0, 0, 0, 255 };
         const PixelUnpackState incompleteUnpackState(1);
 
+        Texture* t = NULL;
         switch (type)
         {
           default:
             UNREACHABLE();
             // default falls through to TEXTURE_2D
 
-          case TEXTURE_2D:
+          case GL_TEXTURE_2D:
             {
                 Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), Texture::INCOMPLETE_TEXTURE_ID);
                 incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
                 t = incomplete2d;
             }
             break;
 
-          case TEXTURE_CUBE:
+          case GL_TEXTURE_CUBE_MAP:
             {
               TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), Texture::INCOMPLETE_TEXTURE_ID);
 
-              incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-              incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-              incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-              incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-              incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-              incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+              incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+              incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+              incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+              incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+              incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+              incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
 
               t = incompleteCube;
             }
             break;
 
-          case TEXTURE_3D:
+          case GL_TEXTURE_3D:
             {
                 Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), Texture::INCOMPLETE_TEXTURE_ID);
                 incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
 
                 t = incomplete3d;
             }
             break;
 
-          case TEXTURE_2D_ARRAY:
+          case GL_TEXTURE_2D_ARRAY:
             {
                 Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), Texture::INCOMPLETE_TEXTURE_ID);
                 incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
 
                 t = incomplete2darray;
             }
             break;
         }
 
         mIncompleteTextures[type].set(t);
     }
 
-    return t;
+    return mIncompleteTextures[type].get();
 }
 
 bool Context::skipDraw(GLenum drawMode)
 {
     if (drawMode == GL_POINTS)
     {
         // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
         // which affects varying interpolation. Since the value of gl_PointSize is
@@ -2228,33 +2298,35 @@ size_t Context::getBoundFramebufferTextu
     size_t serialCount = 0;
 
     Framebuffer *drawFramebuffer = mState.getDrawFramebuffer();
     for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
     {
         FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i);
         if (attachment && attachment->isTexture())
         {
-            (*outSerialArray)[serialCount++] = attachment->getTextureSerial();
+            Texture *texture = attachment->getTexture();
+            (*outSerialArray)[serialCount++] = texture->getTextureSerial();
         }
     }
 
     FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer();
     if (depthStencilAttachment && depthStencilAttachment->isTexture())
     {
-        (*outSerialArray)[serialCount++] = depthStencilAttachment->getTextureSerial();
+        Texture *depthStencilTexture = depthStencilAttachment->getTexture();
+        (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial();
     }
 
     std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount);
 
     return serialCount;
 }
 
-void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                              GLbitfield mask, GLenum filter)
+Error Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                               GLbitfield mask, GLenum filter)
 {
     Framebuffer *readFramebuffer = mState.getReadFramebuffer();
     Framebuffer *drawFramebuffer = mState.getDrawFramebuffer();
 
     bool blitRenderTarget = false;
     bool blitDepth = false;
     bool blitStencil = false;
     if ((mask & GL_COLOR_BUFFER_BIT) && readFramebuffer->getReadColorbuffer() && drawFramebuffer->getFirstColorbuffer())
@@ -2265,24 +2337,30 @@ void Context::blitFramebuffer(GLint srcX
     {
         blitStencil = true;
     }
     if ((mask & GL_DEPTH_BUFFER_BIT) && readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
     {
         blitDepth = true;
     }
 
-    gl::Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
-    gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
+    Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
+    Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
     if (blitRenderTarget || blitDepth || blitStencil)
     {
         const gl::Rectangle *scissor = mState.isScissorTestEnabled() ? &mState.getScissor() : NULL;
-        mRenderer->blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor,
-                            blitRenderTarget, blitDepth, blitStencil, filter);
+        gl::Error error = mRenderer->blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor,
+                                              blitRenderTarget, blitDepth, blitStencil, filter);
+        if (error.isError())
+        {
+            return error;
+        }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Context::releaseShaderCompiler()
 {
     mRenderer->releaseShaderCompiler();
 }
 
 void Context::initCaps(GLuint clientVersion)
@@ -2300,55 +2378,50 @@ void Context::initCaps(GLuint clientVers
     if (clientVersion > 2)
     {
         // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts
         //mExtensions.sRGB = false;
     }
 
     // Apply implementation limits
     mCaps.maxVertexAttributes = std::min<GLuint>(mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS);
-    mCaps.maxVertexTextureImageUnits = std::min<GLuint>(mCaps.maxVertexTextureImageUnits, IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
     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.maxTextureImageUnits = std::min<GLuint>(mCaps.maxTextureImageUnits, MAX_TEXTURE_IMAGE_UNITS);
-
-    mCaps.maxCombinedTextureImageUnits = std::min<GLuint>(mCaps.maxCombinedTextureImageUnits, IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
 
     GLuint maxSamples = 0;
     mCaps.compressedTextureFormats.clear();
 
     const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps();
     for (TextureCapsMap::const_iterator i = rendererFormats.begin(); i != rendererFormats.end(); i++)
     {
         GLenum format = i->first;
         TextureCaps formatCaps = i->second;
 
         const InternalFormat &formatInfo = GetInternalFormatInfo(format);
-        if (formatCaps.texturable && formatInfo.textureSupport(clientVersion, mExtensions))
-        {
-            // Update the format caps based on the client version and extensions
-            formatCaps.renderable = formatInfo.renderSupport(clientVersion, mExtensions);
-            formatCaps.filterable = formatInfo.filterSupport(clientVersion, mExtensions);
+
+        // Update the format caps based on the client version and extensions
+        formatCaps.texturable = formatInfo.textureSupport(clientVersion, mExtensions);
+        formatCaps.renderable = formatInfo.renderSupport(clientVersion, mExtensions);
+        formatCaps.filterable = formatInfo.filterSupport(clientVersion, mExtensions);
 
-            // OpenGL ES does not support multisampling with integer formats
-            if (formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT)
-            {
-                formatCaps.sampleCounts.clear();
-            }
-            maxSamples = std::max(maxSamples, formatCaps.getMaxSamples());
+        // OpenGL ES does not support multisampling with integer formats
+        if (!formatInfo.renderSupport || formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT)
+        {
+            formatCaps.sampleCounts.clear();
+        }
+        maxSamples = std::max(maxSamples, formatCaps.getMaxSamples());
 
-            if (formatInfo.compressed)
-            {
-                mCaps.compressedTextureFormats.push_back(format);
-            }
+        if (formatCaps.texturable && formatInfo.compressed)
+        {
+            mCaps.compressedTextureFormats.push_back(format);
+        }
 
-            mTextureCaps.insert(format, formatCaps);
-        }
+        mTextureCaps.insert(format, formatCaps);
     }
 
     mExtensions.maxSamples = maxSamples;
 }
 
 }
 
 extern "C"
--- a/gfx/angle/src/libGLESv2/Context.h
+++ b/gfx/angle/src/libGLESv2/Context.h
@@ -110,20 +110,17 @@ class Context
     void deleteQuery(GLuint query);
 
     // Vertex arrays are owned by the Context
     GLuint createVertexArray();
     void deleteVertexArray(GLuint vertexArray);
 
     void bindArrayBuffer(GLuint buffer);
     void bindElementArrayBuffer(GLuint buffer);
-    void bindTexture2D(GLuint texture);
-    void bindTextureCubeMap(GLuint texture);
-    void bindTexture3D(GLuint texture);
-    void bindTexture2DArray(GLuint texture);
+    void bindTexture(GLenum target, GLuint texture);
     void bindReadFramebuffer(GLuint framebuffer);
     void bindDrawFramebuffer(GLuint framebuffer);
     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);
@@ -132,18 +129,18 @@ class Context
     void bindCopyWriteBuffer(GLuint buffer);
     void bindPixelPackBuffer(GLuint buffer);
     void bindPixelUnpackBuffer(GLuint buffer);
     void useProgram(GLuint program);
     void linkProgram(GLuint program);
     void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
     void bindTransformFeedback(GLuint transformFeedback);
 
-    void beginQuery(GLenum target, GLuint query);
-    void endQuery(GLenum target);
+    Error beginQuery(GLenum target, GLuint query);
+    Error endQuery(GLenum target);
 
     void setFramebufferZero(Framebuffer *framebuffer);
 
     void setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
 
     void setVertexAttribDivisor(GLuint index, GLuint divisor);
 
     void samplerParameteri(GLuint sampler, GLenum pname, GLint param);
@@ -165,42 +162,42 @@ class Context
     TransformFeedback *getTransformFeedback(GLuint handle) const;
 
     Texture *getTargetTexture(GLenum target) const;
     Texture2D *getTexture2D() const;
     TextureCubeMap *getTextureCubeMap() const;
     Texture3D *getTexture3D() const;
     Texture2DArray *getTexture2DArray() const;
 
-    Texture *getSamplerTexture(unsigned int sampler, TextureType type) const;
+    Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
 
     bool isSampler(GLuint samplerName) const;
 
     void getBooleanv(GLenum pname, GLboolean *params);
     void getFloatv(GLenum pname, GLfloat *params);
     void getIntegerv(GLenum pname, GLint *params);
     void getInteger64v(GLenum pname, GLint64 *params);
 
     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, int drawbuffer, const float *values);
-    void clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values);
-    void clearBufferiv(GLenum buffer, int drawbuffer, const int *values);
-    void clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil);
+    Error clear(GLbitfield mask);
+    Error clearBufferfv(GLenum buffer, int drawbuffer, const float *values);
+    Error clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values);
+    Error clearBufferiv(GLenum buffer, int drawbuffer, const int *values);
+    Error clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil);
 
-    void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
-    void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
-    void drawElements(GLenum mode, GLsizei count, GLenum type,
-                      const GLvoid *indices, GLsizei instances,
-                      const rx::RangeUI &indexRange);
+    Error readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
+    Error drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
+    Error drawElements(GLenum mode, GLsizei count, GLenum type,
+                       const GLvoid *indices, GLsizei instances,
+                       const rx::RangeUI &indexRange);
     void sync(bool block);   // flush/finish
 
     void recordError(const Error &error);
 
     GLenum getError();
     GLenum getResetStatus();
     virtual bool isResetNotificationEnabled();
 
@@ -213,54 +210,54 @@ class Context
     const std::string &getRendererString() const;
 
     const std::string &getExtensionString() const;
     const std::string &getExtensionString(size_t idx) const;
     size_t getExtensionStringCount() const;
 
     void getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type);
 
-    void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
-                         GLbitfield mask, GLenum filter);
+    Error blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+                          GLbitfield mask, GLenum filter);
 
     rx::Renderer *getRenderer() { return mRenderer; }
 
     State &getState() { return mState; }
     const State &getState() const { return mState; }
 
     void releaseShaderCompiler();
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Context);
 
     // TODO: std::array may become unavailable using older versions of GCC
     typedef std::array<unsigned int, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureSerialArray;
 
-    bool applyRenderTarget(GLenum drawMode, bool ignoreViewport);
-    void applyState(GLenum drawMode);
-    void applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive);
-    void applyTextures(SamplerType shaderType, Texture *textures[], TextureType *textureTypes, SamplerState *samplers,
-                       size_t textureCount, const FramebufferTextureSerialArray& framebufferSerials,
-                       size_t framebufferSerialCount);
-    bool applyUniformBuffers();
+    Error applyRenderTarget(GLenum drawMode, bool ignoreViewport);
+    Error applyState(GLenum drawMode);
+    Error applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive);
+    Error applyTextures(ProgramBinary *programBinary, SamplerType shaderType, const FramebufferTextureSerialArray &framebufferSerials,
+                        size_t framebufferSerialCount);
+    Error applyTextures(ProgramBinary *programBinary);
+    Error applyUniformBuffers();
     bool applyTransformFeedbackBuffers();
     void markTransformFeedbackUsage();
 
     void detachBuffer(GLuint buffer);
     void detachTexture(GLuint texture);
     void detachFramebuffer(GLuint framebuffer);
     void detachRenderbuffer(GLuint renderbuffer);
     void detachVertexArray(GLuint vertexArray);
     void detachTransformFeedback(GLuint transformFeedback);
     void detachSampler(GLuint sampler);
 
-    void generateSwizzles(Texture *textures[], size_t count);
-    size_t getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, SamplerType type, Texture **outTextures,
-                                              TextureType *outTextureTypes, SamplerState *outSamplers);
-    Texture *getIncompleteTexture(TextureType type);
+    Error generateSwizzles(ProgramBinary *programBinary, SamplerType type);
+    Error generateSwizzles(ProgramBinary *programBinary);
+
+    Texture *getIncompleteTexture(GLenum type);
 
     bool skipDraw(GLenum drawMode);
 
     void initRendererString();
     void initExtensionStrings();
 
     size_t getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray);
 
@@ -271,20 +268,19 @@ class Context
     TextureCapsMap mTextureCaps;
     Extensions mExtensions;
 
     rx::Renderer *const mRenderer;
     State mState;
 
     int mClientVersion;
 
-    BindingPointer<Texture2D> mTexture2DZero;
-    BindingPointer<TextureCubeMap> mTextureCubeMapZero;
-    BindingPointer<Texture3D> mTexture3DZero;
-    BindingPointer<Texture2DArray> mTexture2DArrayZero;
+    typedef std::map< GLenum, BindingPointer<Texture> > TextureMap;
+    TextureMap mZeroTextures;
+    TextureMap mIncompleteTextures;
 
     typedef std::unordered_map<GLuint, Framebuffer*> FramebufferMap;
     FramebufferMap mFramebufferMap;
     HandleAllocator mFramebufferHandleAllocator;
 
     typedef std::unordered_map<GLuint, FenceNV*> FenceNVMap;
     FenceNVMap mFenceNVMap;
     HandleAllocator mFenceNVHandleAllocator;
@@ -301,18 +297,16 @@ class Context
     typedef std::unordered_map<GLuint, TransformFeedback*> TransformFeedbackMap;
     TransformFeedbackMap mTransformFeedbackMap;
     HandleAllocator mTransformFeedbackAllocator;
 
     std::string mRendererString;
     std::string mExtensionString;
     std::vector<std::string> mExtensionStrings;
 
-    BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT];
-
     // Recorded errors
     typedef std::set<GLenum> ErrorSet;
     ErrorSet mErrors;
 
     // Current/lost context flags
     bool mHasBeenCurrent;
     bool mContextLost;
     GLenum mResetStatus;
--- a/gfx/angle/src/libGLESv2/Framebuffer.cpp
+++ b/gfx/angle/src/libGLESv2/Framebuffer.cpp
@@ -11,19 +11,64 @@
 #include "libGLESv2/main.h"
 #include "libGLESv2/formatutils.h"
 #include "libGLESv2/Texture.h"
 #include "libGLESv2/Context.h"
 #include "libGLESv2/Renderbuffer.h"
 #include "libGLESv2/FramebufferAttachment.h"
 #include "libGLESv2/renderer/Renderer.h"
 #include "libGLESv2/renderer/RenderTarget.h"
+#include "libGLESv2/renderer/Workarounds.h"
+#include "libGLESv2/renderer/d3d/TextureD3D.h"
 
 #include "common/utilities.h"
 
+namespace rx
+{
+RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
+{
+    if (attachment->isTexture())
+    {
+        gl::Texture *texture = attachment->getTexture();
+        ASSERT(texture);
+        TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+        const gl::ImageIndex *index = attachment->getTextureImageIndex();
+        ASSERT(index);
+        return textureD3D->getRenderTarget(*index);
+    }
+
+    gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
+    ASSERT(renderbuffer);
+
+    // TODO: cast to RenderbufferD3D
+    return renderbuffer->getStorage()->getRenderTarget();
+}
+
+// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
+unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
+{
+    if (attachment->isTexture())
+    {
+        gl::Texture *texture = attachment->getTexture();
+        ASSERT(texture);
+        TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+        const gl::ImageIndex *index = attachment->getTextureImageIndex();
+        ASSERT(index);
+        return textureD3D->getRenderTargetSerial(*index);
+    }
+
+    gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
+    ASSERT(renderbuffer);
+
+    // TODO: cast to RenderbufferD3D
+    return renderbuffer->getStorage()->getSerial();
+}
+
+}
+
 namespace gl
 {
 
 Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id)
     : mRenderer(renderer),
       mId(id),
       mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
       mDepthbuffer(NULL),
@@ -42,40 +87,39 @@ Framebuffer::~Framebuffer()
     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
     {
         SafeDelete(mColorbuffers[colorAttachment]);
     }
     SafeDelete(mDepthbuffer);
     SafeDelete(mStencilbuffer);
 }
 
-FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const
+FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const
 {
     if (handle == 0)
     {
         return NULL;
     }
 
     gl::Context *context = gl::getContext();
 
     switch (type)
     {
       case GL_NONE:
         return NULL;
 
       case GL_RENDERBUFFER:
-        return new RenderbufferAttachment(context->getRenderbuffer(handle));
+        return new RenderbufferAttachment(binding, context->getRenderbuffer(handle));
 
       case GL_TEXTURE_2D:
         {
             Texture *texture = context->getTexture(handle);
             if (texture && texture->getTarget() == GL_TEXTURE_2D)
             {
-                Texture2D *tex2D = static_cast<Texture2D*>(texture);
-                return new Texture2DAttachment(tex2D, level);
+                return new TextureAttachment(binding, texture, ImageIndex::Make2D(level));
             }
             else
             {
                 return NULL;
             }
         }
 
       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
@@ -83,46 +127,43 @@ FramebufferAttachment *Framebuffer::crea
       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
         {
             Texture *texture = context->getTexture(handle);
             if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
             {
-                TextureCubeMap *texCube = static_cast<TextureCubeMap*>(texture);
-                return new TextureCubeMapAttachment(texCube, type, level);
+                return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level));
             }
             else
             {
                 return NULL;
             }
         }
 
       case GL_TEXTURE_3D:
         {
             Texture *texture = context->getTexture(handle);
             if (texture && texture->getTarget() == GL_TEXTURE_3D)
             {
-                Texture3D *tex3D = static_cast<Texture3D*>(texture);
-                return new Texture3DAttachment(tex3D, level, layer);
+                return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer));
             }
             else
             {
                 return NULL;
             }
         }
 
       case GL_TEXTURE_2D_ARRAY:
         {
             Texture *texture = context->getTexture(handle);
             if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
             {
-                Texture2DArray *tex2DArray = static_cast<Texture2DArray*>(texture);
-                return new Texture2DArrayAttachment(tex2DArray, level, layer);
+                return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer));
             }
             else
             {
                 return NULL;
             }
         }
 
       default:
@@ -130,46 +171,47 @@ FramebufferAttachment *Framebuffer::crea
         return NULL;
     }
 }
 
 void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
 {
     ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
     SafeDelete(mColorbuffers[colorAttachment]);
-    mColorbuffers[colorAttachment] = createAttachment(type, colorbuffer, level, layer);
+    GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0;
+    mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer);
 }
 
 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
 {
     SafeDelete(mDepthbuffer);
-    mDepthbuffer = createAttachment(type, depthbuffer, level, layer);
+    mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer);
 }
 
 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
 {
     SafeDelete(mStencilbuffer);
-    mStencilbuffer = createAttachment(type, stencilbuffer, level, layer);
+    mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer);
 }
 
 void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
 {
-    FramebufferAttachment *attachment = createAttachment(type, depthStencilBuffer, level, layer);
+    FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
 
     SafeDelete(mDepthbuffer);
     SafeDelete(mStencilbuffer);
 
     // ensure this is a legitimate depth+stencil format
     if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
     {
         mDepthbuffer = attachment;
 
         // Make a new attachment object to ensure we do not double-delete
         // See angle issue 686
-        mStencilbuffer = createAttachment(type, depthStencilBuffer, level, layer);
+        mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
     }
 }
 
 void Framebuffer::detachTexture(GLuint textureId)
 {
     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
     {
         FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
@@ -566,81 +608,47 @@ void Framebuffer::invalidate(const Caps 
     GLuint maxDimension = caps.maxRenderbufferSize;
     invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension);
 }
 
 void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments,
                                 GLint x, GLint y, GLsizei width, GLsizei height)
 {
     ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE);
-    for (int i = 0; i < numAttachments; ++i)
+    for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex)
     {
-        rx::RenderTarget *renderTarget = NULL;
+        GLenum attachmentTarget = attachments[attachIndex];
 
-        if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
+        gl::FramebufferAttachment *attachment =
+            (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() :
+                                                                getAttachment(attachmentTarget);
+
+        if (attachment)
         {
-            gl::FramebufferAttachment *attachment = getColorbuffer(attachments[i] - GL_COLOR_ATTACHMENT0);
-            if (attachment)
-            {
-                renderTarget = attachment->getRenderTarget();
-            }
-        }
-        else if (attachments[i] == GL_COLOR)
-        {
-            gl::FramebufferAttachment *attachment = getColorbuffer(0);
-            if (attachment)
-            {
-                renderTarget = attachment->getRenderTarget();
-            }
-        }
-        else
-        {
-            gl::FramebufferAttachment *attachment = NULL;
-            switch (attachments[i])
+            rx::RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
+            if (renderTarget)
             {
-              case GL_DEPTH_ATTACHMENT:
-              case GL_DEPTH:
-                attachment = mDepthbuffer;
-                break;
-              case GL_STENCIL_ATTACHMENT:
-              case GL_STENCIL:
-                attachment = mStencilbuffer;
-                break;
-              case GL_DEPTH_STENCIL_ATTACHMENT:
-                attachment = getDepthOrStencilbuffer();
-                break;
-              default:
-                UNREACHABLE();
+                renderTarget->invalidate(x, y, width, height);
             }
-
-            if (attachment)
-            {
-                renderTarget = attachment->getRenderTarget();
-            }
-        }
-
-        if (renderTarget)
-        {
-            renderTarget->invalidate(x, y, width, height);
         }
     }
 }
 
 DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
     : Framebuffer(renderer, 0)
 {
     Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer);
-    mColorbuffers[0] = new RenderbufferAttachment(colorRenderbuffer);
+    mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer);
 
     Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil);
 
     // Make a new attachment objects to ensure we do not double-delete
     // See angle issue 686
-    mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(depthStencilBuffer) : NULL);
-    mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(depthStencilBuffer) : NULL);
+    mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL);
+    mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL);
 
     mDrawBufferStates[0] = GL_BACK;
     mReadBufferState = GL_BACK;
 }
 
 int Framebuffer::getSamples() const
 {
     if (completeness() == GL_FRAMEBUFFER_COMPLETE)
@@ -663,27 +671,51 @@ bool Framebuffer::hasValidDepthStencil()
 {
     // A valid depth-stencil attachment has the same resource bound to both the
     // depth and stencil attachment points.
     return (mDepthbuffer && mStencilbuffer &&
             mDepthbuffer->type() == mStencilbuffer->type() &&
             mDepthbuffer->id() == mStencilbuffer->id());
 }
 
+ColorbufferInfo Framebuffer::getColorbuffersForRender() const
+{
+    ColorbufferInfo colorbuffersForRender;
+
+    for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment)
+    {
+        GLenum drawBufferState = mDrawBufferStates[colorAttachment];
+        FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
+
+        if (colorbuffer != NULL && drawBufferState != GL_NONE)
+        {
+            ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
+            colorbuffersForRender.push_back(colorbuffer);
+        }
+        else if (!mRenderer->getWorkarounds().mrtPerfWorkaround)
+        {
+            colorbuffersForRender.push_back(NULL);
+        }
+    }
+
+    return colorbuffersForRender;
+}
+
 GLenum DefaultFramebuffer::completeness() const
 {
     // The default framebuffer *must* always be complete, though it may not be
     // subject to the same rules as application FBOs. ie, it could have 0x0 size.
     return GL_FRAMEBUFFER_COMPLETE;
 }
 
 FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const
 {
     switch (attachment)
     {
+      case GL_COLOR:
       case GL_BACK:
         return getColorbuffer(0);
       case GL_DEPTH:
         return getDepthbuffer();
       case GL_STENCIL:
         return getStencilbuffer();
       case GL_DEPTH_STENCIL:
         return getDepthStencilBuffer();
--- a/gfx/angle/src/libGLESv2/Framebuffer.h
+++ b/gfx/angle/src/libGLESv2/Framebuffer.h
@@ -5,16 +5,18 @@
 //
 
 // Framebuffer.h: Defines the gl::Framebuffer class. Implements GL framebuffer
 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
 
 #ifndef LIBGLESV2_FRAMEBUFFER_H_
 #define LIBGLESV2_FRAMEBUFFER_H_
 
+#include <vector>
+
 #include "common/angleutils.h"
 #include "common/RefCountObject.h"
 #include "Constants.h"
 
 namespace rx
 {
 class Renderer;
 }
@@ -23,16 +25,18 @@ namespace gl
 {
 class FramebufferAttachment;
 class Colorbuffer;
 class Depthbuffer;
 class Stencilbuffer;
 class DepthStencilbuffer;
 struct Caps;
 
+typedef std::vector<FramebufferAttachment *> ColorbufferInfo;
+
 class Framebuffer
 {
   public:
     Framebuffer(rx::Renderer *renderer, GLuint id);
 
     virtual ~Framebuffer();
 
     GLuint id() const { return mId; }
@@ -67,41 +71,56 @@ class Framebuffer
 
     virtual GLenum completeness() const;
     bool hasValidDepthStencil() const;
 
     void invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments);
     void invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments,
                        GLint x, GLint y, GLsizei width, GLsizei height);
 
+    // Use this method to retrieve the color buffer map when doing rendering.
+    // It will apply a workaround for poor shader performance on some systems
+    // by compacting the list to skip NULL values.
+    ColorbufferInfo getColorbuffersForRender() const;
+
   protected:
     rx::Renderer *mRenderer;
 
     GLuint mId;
 
     FramebufferAttachment *mColorbuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
     GLenum mDrawBufferStates[IMPLEMENTATION_MAX_DRAW_BUFFERS];
     GLenum mReadBufferState;
 
     FramebufferAttachment *mDepthbuffer;
     FramebufferAttachment *mStencilbuffer;
 
-private:
+  private:
     DISALLOW_COPY_AND_ASSIGN(Framebuffer);
 
-    FramebufferAttachment *createAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const;
+    FramebufferAttachment *createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const;
 };
 
 class DefaultFramebuffer : public Framebuffer
 {
   public:
     DefaultFramebuffer(rx::Renderer *Renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil);
 
     virtual GLenum completeness() const;
     virtual FramebufferAttachment *getAttachment(GLenum attachment) const;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer);
 };
 
 }
 
+namespace rx
+{
+class RenderTarget;
+
+// TODO: place this in FramebufferD3D.h
+RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment);
+unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment);
+
+}
+
 #endif   // LIBGLESV2_FRAMEBUFFER_H_
--- a/gfx/angle/src/libGLESv2/FramebufferAttachment.cpp
+++ b/gfx/angle/src/libGLESv2/FramebufferAttachment.cpp
@@ -17,17 +17,18 @@
 
 #include "common/utilities.h"
 
 namespace gl
 {
 
 ////// FramebufferAttachment Implementation //////
 
-FramebufferAttachment::FramebufferAttachment()
+FramebufferAttachment::FramebufferAttachment(GLenum binding)
+    : mBinding(binding)
 {
 }
 
 FramebufferAttachment::~FramebufferAttachment()
 {
 }
 
 GLuint FramebufferAttachment::getRedSize() const
@@ -70,351 +71,105 @@ GLenum FramebufferAttachment::getColorEn
     return GetInternalFormatInfo(getActualFormat()).colorEncoding;
 }
 
 bool FramebufferAttachment::isTexture() const
 {
     return (type() != GL_RENDERBUFFER);
 }
 
-///// Texture2DAttachment Implementation ////////
-
-Texture2DAttachment::Texture2DAttachment(Texture2D *texture, GLint level) : mLevel(level)
-{
-    mTexture2D.set(texture);
-}
-
-Texture2DAttachment::~Texture2DAttachment()
-{
-    mTexture2D.set(NULL);
-}
-
-rx::RenderTarget *Texture2DAttachment::getRenderTarget()
-{
-    return mTexture2D->getRenderTarget(mLevel);
-}
+///// TextureAttachment Implementation ////////
 
-rx::TextureStorage *Texture2DAttachment::getTextureStorage()
-{
-    return mTexture2D->getNativeTexture()->getStorageInstance();
-}
-
-GLsizei Texture2DAttachment::getWidth() const
-{
-    return mTexture2D->getWidth(mLevel);
-}
-
-GLsizei Texture2DAttachment::getHeight() const
-{
-    return mTexture2D->getHeight(mLevel);
-}
-
-GLenum Texture2DAttachment::getInternalFormat() const
+TextureAttachment::TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index)
+    : FramebufferAttachment(binding),
+      mIndex(index)
 {
-    return mTexture2D->getInternalFormat(mLevel);
-}
-
-GLenum Texture2DAttachment::getActualFormat() const
-{
-    return mTexture2D->getActualFormat(mLevel);
-}
-
-GLsizei Texture2DAttachment::getSamples() const
-{
-    return 0;
-}
-
-unsigned int Texture2DAttachment::getSerial() const
-{
-    return mTexture2D->getRenderTargetSerial(mLevel);
-}
-
-GLuint Texture2DAttachment::id() const
-{
-    return mTexture2D->id();
-}
-
-GLenum Texture2DAttachment::type() const
-{
-    return GL_TEXTURE_2D;
-}
-
-GLint Texture2DAttachment::mipLevel() const
-{
-    return mLevel;
-}
-
-GLint Texture2DAttachment::layer() const
-{
-    return 0;
+    mTexture.set(texture);
 }
 
-unsigned int Texture2DAttachment::getTextureSerial() const
-{
-    return mTexture2D->getTextureSerial();
-}
-
-///// TextureCubeMapAttachment Implementation ////////
-
-TextureCubeMapAttachment::TextureCubeMapAttachment(TextureCubeMap *texture, GLenum faceTarget, GLint level)
-    : mFaceTarget(faceTarget), mLevel(level)
-{
-    mTextureCubeMap.set(texture);
-}
-
-TextureCubeMapAttachment::~TextureCubeMapAttachment()
+TextureAttachment::~TextureAttachment()
 {
-    mTextureCubeMap.set(NULL);
-}
-
-rx::RenderTarget *TextureCubeMapAttachment::getRenderTarget()
-{
-    return mTextureCubeMap->getRenderTarget(mFaceTarget, mLevel);
-}
-
-rx::TextureStorage *TextureCubeMapAttachment::getTextureStorage()
-{
-    return mTextureCubeMap->getNativeTexture()->getStorageInstance();
-}
-
-GLsizei TextureCubeMapAttachment::getWidth() const
-{
-    return mTextureCubeMap->getWidth(mFaceTarget, mLevel);
+    mTexture.set(NULL);
 }
 
-GLsizei TextureCubeMapAttachment::getHeight() const
-{
-    return mTextureCubeMap->getHeight(mFaceTarget, mLevel);
-}
-
-GLenum TextureCubeMapAttachment::getInternalFormat() const
-{
-    return mTextureCubeMap->getInternalFormat(mFaceTarget, mLevel);
-}
-
-GLenum TextureCubeMapAttachment::getActualFormat() const
-{
-    return mTextureCubeMap->getActualFormat(mFaceTarget, mLevel);
-}
-
-GLsizei TextureCubeMapAttachment::getSamples() const
-{
-    return 0;
-}
-
-unsigned int TextureCubeMapAttachment::getSerial() const
-{
-    return mTextureCubeMap->getRenderTargetSerial(mFaceTarget, mLevel);
-}
-
-GLuint TextureCubeMapAttachment::id() const
-{
-    return mTextureCubeMap->id();
-}
-
-GLenum TextureCubeMapAttachment::type() const
-{
-    return mFaceTarget;
-}
-
-GLint TextureCubeMapAttachment::mipLevel() const
-{
-    return mLevel;
-}
-
-GLint TextureCubeMapAttachment::layer() const
+GLsizei TextureAttachment::getSamples() const
 {
     return 0;
 }
 
-unsigned int TextureCubeMapAttachment::getTextureSerial() const
+GLuint TextureAttachment::id() const
 {
-    return mTextureCubeMap->getTextureSerial();
-}
-
-///// Texture3DAttachment Implementation ////////
-
-Texture3DAttachment::Texture3DAttachment(Texture3D *texture, GLint level, GLint layer)
-    : mLevel(level), mLayer(layer)
-{
-    mTexture3D.set(texture);
-}
-
-Texture3DAttachment::~Texture3DAttachment()
-{
-    mTexture3D.set(NULL);
+    return mTexture->id();
 }
 
-rx::RenderTarget *Texture3DAttachment::getRenderTarget()
-{
-    return mTexture3D->getRenderTarget(mLevel, mLayer);
-}
-
-rx::TextureStorage *Texture3DAttachment::getTextureStorage()
+GLsizei TextureAttachment::getWidth() const
 {
-    return mTexture3D->getNativeTexture()->getStorageInstance();
-}
-
-GLsizei Texture3DAttachment::getWidth() const
-{
-    return mTexture3D->getWidth(mLevel);
-}
-
-GLsizei Texture3DAttachment::getHeight() const
-{
-    return mTexture3D->getHeight(mLevel);
+    return mTexture->getWidth(mIndex);
 }
 
-GLenum Texture3DAttachment::getInternalFormat() const
-{
-    return mTexture3D->getInternalFormat(mLevel);
-}
-
-GLenum Texture3DAttachment::getActualFormat() const
+GLsizei TextureAttachment::getHeight() const
 {
-    return mTexture3D->getActualFormat(mLevel);
-}
-
-GLsizei Texture3DAttachment::getSamples() const
-{
-    return 0;
+    return mTexture->getHeight(mIndex);
 }
 
-unsigned int Texture3DAttachment::getSerial() const
+GLenum TextureAttachment::getInternalFormat() const
 {
-    return mTexture3D->getRenderTargetSerial(mLevel, mLayer);
-}
-
-GLuint Texture3DAttachment::id() const
-{
-    return mTexture3D->id();
+    return mTexture->getInternalFormat(mIndex);
 }
 
-GLenum Texture3DAttachment::type() const
-{
-    return GL_TEXTURE_3D;
-}
-
-GLint Texture3DAttachment::mipLevel() const
+GLenum TextureAttachment::getActualFormat() const
 {
-    return mLevel;
-}
-
-GLint Texture3DAttachment::layer() const
-{
-    return mLayer;
+    return mTexture->getActualFormat(mIndex);
 }
 
-unsigned int Texture3DAttachment::getTextureSerial() const
+GLenum TextureAttachment::type() const
 {
-    return mTexture3D->getTextureSerial();
-}
-
-////// Texture2DArrayAttachment Implementation //////
-
-Texture2DArrayAttachment::Texture2DArrayAttachment(Texture2DArray *texture, GLint level, GLint layer)
-    : mLevel(level), mLayer(layer)
-{
-    mTexture2DArray.set(texture);
-}
-
-Texture2DArrayAttachment::~Texture2DArrayAttachment()
-{
-    mTexture2DArray.set(NULL);
+    return mIndex.type;
 }
 
-rx::RenderTarget *Texture2DArrayAttachment::getRenderTarget()
+GLint TextureAttachment::mipLevel() const
 {
-    return mTexture2DArray->getRenderTarget(mLevel, mLayer);
+    return mIndex.mipIndex;
 }
 
-rx::TextureStorage *Texture2DArrayAttachment::getTextureStorage()
-{
-    return mTexture2DArray->getNativeTexture()->getStorageInstance();
-}
-
-GLsizei Texture2DArrayAttachment::getWidth() const
+GLint TextureAttachment::layer() const
 {
-    return mTexture2DArray->getWidth(mLevel);
-}
-
-GLsizei Texture2DArrayAttachment::getHeight() const
-{
-    return mTexture2DArray->getHeight(mLevel);
+    return mIndex.layerIndex;
 }
 
-GLenum Texture2DArrayAttachment::getInternalFormat() const
-{
-    return mTexture2DArray->getInternalFormat(mLevel);
-}
-
-GLenum Texture2DArrayAttachment::getActualFormat() const
+Texture *TextureAttachment::getTexture()
 {
-    return mTexture2DArray->getActualFormat(mLevel);
-}
-
-GLsizei Texture2DArrayAttachment::getSamples() const
-{
-    return 0;
-}
-
-unsigned int Texture2DArrayAttachment::getSerial() const
-{
-    return mTexture2DArray->getRenderTargetSerial(mLevel, mLayer);
+    return mTexture.get();
 }
 
-GLuint Texture2DArrayAttachment::id() const
+const ImageIndex *TextureAttachment::getTextureImageIndex() const
 {
-    return mTexture2DArray->id();
-}
-
-GLenum Texture2DArrayAttachment::type() const
-{
-    return GL_TEXTURE_2D_ARRAY;
+    return &mIndex;
 }
 
-GLint Texture2DArrayAttachment::mipLevel() const
-{
-    return mLevel;
-}
-
-GLint Texture2DArrayAttachment::layer() const
+Renderbuffer *TextureAttachment::getRenderbuffer()
 {
-    return mLayer;
-}
-
-unsigned int Texture2DArrayAttachment::getTextureSerial() const
-{
-    return mTexture2DArray->getTextureSerial();
+    UNREACHABLE();
+    return NULL;
 }
 
 ////// RenderbufferAttachment Implementation //////
 
-RenderbufferAttachment::RenderbufferAttachment(Renderbuffer *renderbuffer)
+RenderbufferAttachment::RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer)
+    : FramebufferAttachment(binding)
 {
     ASSERT(renderbuffer);
     mRenderbuffer.set(renderbuffer);
 }
 
 RenderbufferAttachment::~RenderbufferAttachment()
 {
     mRenderbuffer.set(NULL);
 }
 
-rx::RenderTarget *RenderbufferAttachment::getRenderTarget()
-{
-    return mRenderbuffer->getStorage()->getRenderTarget();
-}
-
-rx::TextureStorage *RenderbufferAttachment::getTextureStorage()
-{
-    UNREACHABLE();
-    return NULL;
-}
-
 GLsizei RenderbufferAttachment::getWidth() const
 {
     return mRenderbuffer->getWidth();
 }
 
 GLsizei RenderbufferAttachment::getHeight() const
 {
     return mRenderbuffer->getHeight();
@@ -430,21 +185,16 @@ GLenum RenderbufferAttachment::getActual
     return mRenderbuffer->getActualFormat();
 }
 
 GLsizei RenderbufferAttachment::getSamples() const
 {
     return mRenderbuffer->getStorage()->getSamples();
 }
 
-unsigned int RenderbufferAttachment::getSerial() const
-{
-    return mRenderbuffer->getStorage()->getSerial();
-}
-
 GLuint RenderbufferAttachment::id() const
 {
     return mRenderbuffer->id();
 }
 
 GLenum RenderbufferAttachment::type() const
 {
     return GL_RENDERBUFFER;
@@ -455,15 +205,26 @@ GLint RenderbufferAttachment::mipLevel()
     return 0;
 }
 
 GLint RenderbufferAttachment::layer() const
 {
     return 0;
 }
 
-unsigned int RenderbufferAttachment::getTextureSerial() const
+Texture *RenderbufferAttachment::getTexture()
 {
     UNREACHABLE();
-    return 0;
+    return NULL;
+}
+
+const ImageIndex *RenderbufferAttachment::getTextureImageIndex() const
+{
+    UNREACHABLE();
+    return NULL;
+}
+
+Renderbuffer *RenderbufferAttachment::getRenderbuffer()
+{
+    return mRenderbuffer.get();
 }
 
 }
--- a/gfx/angle/src/libGLESv2/FramebufferAttachment.h
+++ b/gfx/angle/src/libGLESv2/FramebufferAttachment.h
@@ -7,232 +7,131 @@
 // FramebufferAttachment.h: Defines the wrapper class gl::FramebufferAttachment, as well as the
 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
 
 #ifndef LIBGLESV2_FRAMEBUFFERATTACHMENT_H_
 #define LIBGLESV2_FRAMEBUFFERATTACHMENT_H_
 
 #include "common/angleutils.h"
 #include "common/RefCountObject.h"
+#include "Texture.h"
 
 #include "angle_gl.h"
 
 namespace rx
 {
 class Renderer;
 class RenderTarget;
 class TextureStorage;
 }
 
 namespace gl
 {
-class Texture2D;
-class TextureCubeMap;
-class Texture3D;
-class Texture2DArray;
 class Renderbuffer;
 
 // FramebufferAttachment implements a GL framebuffer attachment.
 // Attachments are "light" containers, which store pointers to ref-counted GL objects.
 // We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments.
 // Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for
 // framebuffer attachments, which confused their usage.
 
 class FramebufferAttachment
 {
   public:
-    FramebufferAttachment();
+    explicit FramebufferAttachment(GLenum binding);
     virtual ~FramebufferAttachment();
 
     // Helper methods
     GLuint getRedSize() const;
     GLuint getGreenSize() const;
     GLuint getBlueSize() const;
     GLuint getAlphaSize() const;
     GLuint getDepthSize() const;
     GLuint getStencilSize() const;
     GLenum getComponentType() const;
     GLenum getColorEncoding() const;
     bool isTexture() const;
 
     bool isTextureWithId(GLuint textureId) const { return isTexture() && id() == textureId; }
     bool isRenderbufferWithId(GLuint renderbufferId) const { return !isTexture() && id() == renderbufferId; }
 
+    GLenum getBinding() const { return mBinding; }
+
     // Child class interface
-    virtual rx::RenderTarget *getRenderTarget() = 0;
-    virtual rx::TextureStorage *getTextureStorage() = 0;
-
     virtual GLsizei getWidth() const = 0;
     virtual GLsizei getHeight() const = 0;
     virtual GLenum getInternalFormat() const = 0;
     virtual GLenum getActualFormat() const = 0;
     virtual GLsizei getSamples() const = 0;
 
-    virtual unsigned int getSerial() const = 0;
-
     virtual GLuint id() const = 0;
     virtual GLenum type() const = 0;
     virtual GLint mipLevel() const = 0;
     virtual GLint layer() const = 0;
-    virtual unsigned int getTextureSerial() const = 0;
+
+    virtual Texture *getTexture() = 0;
+    virtual const ImageIndex *getTextureImageIndex() const = 0;
+    virtual Renderbuffer *getRenderbuffer() = 0;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(FramebufferAttachment);
+
+    GLenum mBinding;
 };
 
-class Texture2DAttachment : public FramebufferAttachment
+class TextureAttachment : public FramebufferAttachment
 {
   public:
-    Texture2DAttachment(Texture2D *texture, GLint level);
+    TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index);
+    virtual ~TextureAttachment();
 
-    virtual ~Texture2DAttachment();
-
-    rx::RenderTarget *getRenderTarget();
-    rx::TextureStorage *getTextureStorage();
+    virtual GLsizei getSamples() const;
+    virtual GLuint id() const;
 
     virtual GLsizei getWidth() const;
     virtual GLsizei getHeight() const;
     virtual GLenum getInternalFormat() const;
     virtual GLenum getActualFormat() const;
-    virtual GLsizei getSamples() const;
 
-    virtual unsigned int getSerial() const;
-
-    virtual GLuint id() const;
     virtual GLenum type() const;
     virtual GLint mipLevel() const;
     virtual GLint layer() const;
-    virtual unsigned int getTextureSerial() const;
+
+    virtual Texture *getTexture();
+    virtual const ImageIndex *getTextureImageIndex() const;
+    virtual Renderbuffer *getRenderbuffer();
 
   private:
-    DISALLOW_COPY_AND_ASSIGN(Texture2DAttachment);
+    DISALLOW_COPY_AND_ASSIGN(TextureAttachment);
 
-    BindingPointer<Texture2D> mTexture2D;
-    const GLint mLevel;
+    BindingPointer<Texture> mTexture;
+    ImageIndex mIndex;
 };
 
-class TextureCubeMapAttachment : public FramebufferAttachment
+class RenderbufferAttachment : public FramebufferAttachment
 {
   public:
-    TextureCubeMapAttachment(TextureCubeMap *texture, GLenum faceTarget, GLint level);
+    RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer);
 
-    virtual ~TextureCubeMapAttachment();
-
-    rx::RenderTarget *getRenderTarget();
-    rx::TextureStorage *getTextureStorage();
+    virtual ~RenderbufferAttachment();
 
     virtual GLsizei getWidth() const;
     virtual GLsizei getHeight() const;
     virtual GLenum getInternalFormat() const;
     virtual GLenum getActualFormat() const;
     virtual GLsizei getSamples() const;
 
-    virtual unsigned int getSerial() const;
-
-    virtual GLuint id() const;
-    virtual GLenum type() const;
-    virtual GLint mipLevel() const;
-    virtual GLint layer() const;
-    virtual unsigned int getTextureSerial() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(TextureCubeMapAttachment);
-
-    BindingPointer<TextureCubeMap> mTextureCubeMap;
-    const GLint mLevel;
-    const GLenum mFaceTarget;
-};
-
-class Texture3DAttachment : public FramebufferAttachment
-{
-  public:
-    Texture3DAttachment(Texture3D *texture, GLint level, GLint layer);
-
-    virtual ~Texture3DAttachment();
-
-    rx::RenderTarget *getRenderTarget();
-    rx::TextureStorage *getTextureStorage();
-
-    virtual GLsizei getWidth() const;
-    virtual GLsizei getHeight() const;
-    virtual GLenum getInternalFormat() const;
-    virtual GLenum getActualFormat() const;
-    virtual GLsizei getSamples() const;
-
-    virtual unsigned int getSerial() const;
-
     virtual GLuint id() const;
     virtual GLenum type() const;
     virtual GLint mipLevel() const;
     virtual GLint layer() const;
-    virtual unsigned int getTextureSerial() const;
 
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Texture3DAttachment);
-
-    BindingPointer<Texture3D> mTexture3D;
-    const GLint mLevel;
-    const GLint mLayer;
-};
-
-class Texture2DArrayAttachment : public FramebufferAttachment
-{
-  public:
-    Texture2DArrayAttachment(Texture2DArray *texture, GLint level, GLint layer);
-
-    virtual ~Texture2DArrayAttachment();
-
-    rx::RenderTarget *getRenderTarget();
-    rx::TextureStorage *getTextureStorage();
-
-    virtual GLsizei getWidth() const;
-    virtual GLsizei getHeight() const;
-    virtual GLenum getInternalFormat() const;
-    virtual GLenum getActualFormat() const;
-    virtual GLsizei getSamples() const;
-
-    virtual unsigned int getSerial() const;
-
-    virtual GLuint id() const;
-    virtual GLenum type() const;
-    virtual GLint mipLevel() const;
-    virtual GLint layer() const;
-    virtual unsigned int getTextureSerial() const;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Texture2DArrayAttachment);
-
-    BindingPointer<Texture2DArray> mTexture2DArray;
-    const GLint mLevel;
-    const GLint mLayer;
-};
-
-class RenderbufferAttachment : public FramebufferAttachment
-{
-  public:
-    RenderbufferAttachment(Renderbuffer *renderbuffer);
-
-    virtual ~RenderbufferAttachment();
-
-    rx::RenderTarget *getRenderTarget();
-    rx::TextureStorage *getTextureStorage();
-
-    virtual GLsizei getWidth() const;
-    virtual GLsizei getHeight() const;
-    virtual GLenum getInternalFormat() const;
-    virtual GLenum getActualFormat() const;
-    virtual GLsizei getSamples() const;
-
-    virtual unsigned int getSerial() const;
-
-    virtual GLuint id() const;
-    virtual GLenum type() const;
-    virtual GLint mipLevel() const;
-    virtual GLint layer() const;
-    virtual unsigned int getTextureSerial() const;
+    virtual Texture *getTexture();
+    virtual const ImageIndex *getTextureImageIndex() const;
+    virtual Renderbuffer *getRenderbuffer();
 
   private:
     DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment);
 
     BindingPointer<Renderbuffer> mRenderbuffer;
 };
 
 }
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libGLESv2/ImageIndex.cpp
@@ -0,0 +1,143 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ImageIndex.cpp: Implementation for ImageIndex methods.
+
+#include "libGLESv2/ImageIndex.h"
+#include "libGLESv2/Texture.h"
+#include "common/utilities.h"
+
+namespace gl
+{
+
+ImageIndex::ImageIndex(const ImageIndex &other)
+    : type(other.type),
+      mipIndex(other.mipIndex),
+      layerIndex(other.layerIndex)
+{}
+
+ImageIndex &ImageIndex::operator=(const ImageIndex &other)
+{
+    type = other.type;
+    mipIndex = other.mipIndex;
+    layerIndex = other.layerIndex;
+    return *this;
+}
+
+ImageIndex ImageIndex::Make2D(GLint mipIndex)
+{
+    return ImageIndex(GL_TEXTURE_2D, mipIndex, ENTIRE_LEVEL);
+}
+
+ImageIndex ImageIndex::MakeCube(GLenum target, GLint mipIndex)
+{
+    ASSERT(gl::IsCubemapTextureTarget(target));
+    return ImageIndex(target, mipIndex, TextureCubeMap::targetToLayerIndex(target));
+}
+
+ImageIndex ImageIndex::Make2DArray(GLint mipIndex, GLint layerIndex)
+{
+    return ImageIndex(GL_TEXTURE_2D_ARRAY, mipIndex, layerIndex);
+}
+
+ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex)
+{
+    return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex);
+}
+
+ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn)
+    : type(typeIn),
+      mipIndex(mipIndexIn),
+      layerIndex(layerIndexIn)
+{}
+
+ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
+{
+    return ImageIndexIterator(GL_TEXTURE_2D, rx::Range<GLint>(minMip, maxMip),
+                              rx::Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), NULL);
+}
+
+ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
+{
+    return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, rx::Range<GLint>(minMip, maxMip), rx::Range<GLint>(0, 6), NULL);
+}
+
+ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip,
+                                              GLint minLayer, GLint maxLayer)
+{
+    return ImageIndexIterator(GL_TEXTURE_3D, rx::Range<GLint>(minMip, maxMip), rx::Range<GLint>(minLayer, maxLayer), NULL);
+}
+
+ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip,
+                                                   const GLsizei *layerCounts)
+{
+    return ImageIndexIterator(GL_TEXTURE_2D_ARRAY, rx::Range<GLint>(minMip, maxMip),
+                              rx::Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS), layerCounts);
+}
+
+ImageIndexIterator::ImageIndexIterator(GLenum type, const rx::Range<GLint> &mipRange,
+                                       const rx::Range<GLint> &layerRange, const GLsizei *layerCounts)
+    : mType(type),
+      mMipRange(mipRange),
+      mLayerRange(layerRange),
+      mLayerCounts(layerCounts),
+      mCurrentMip(mipRange.start),
+      mCurrentLayer(layerRange.start)
+{}
+
+GLint ImageIndexIterator::maxLayer() const
+{
+    return (mLayerCounts ? static_cast<GLint>(mLayerCounts[mCurrentMip]) : mLayerRange.end);
+}
+
+ImageIndex ImageIndexIterator::next()
+{
+    ASSERT(hasNext());
+
+    ImageIndex value = current();
+
+    // Iterate layers in the inner loop for now. We can add switchable
+    // layer or mip iteration if we need it.
+
+    if (mCurrentLayer != ImageIndex::ENTIRE_LEVEL)
+    {
+        if (mCurrentLayer < maxLayer()-1)
+        {
+            mCurrentLayer++;
+        }
+        else if (mCurrentMip < mMipRange.end-1)
+        {
+            mCurrentMip++;
+            mCurrentLayer = mLayerRange.start;
+        }
+    }
+    else if (mCurrentMip < mMipRange.end-1)
+    {
+        mCurrentMip++;
+        mCurrentLayer = mLayerRange.start;
+    }
+
+    return value;
+}
+
+ImageIndex ImageIndexIterator::current() const
+{
+    ImageIndex value(mType, mCurrentMip, mCurrentLayer);
+
+    if (mType == GL_TEXTURE_CUBE_MAP)
+    {
+        value.type = TextureCubeMap::layerIndexToTarget(mCurrentLayer);
+    }
+
+    return value;
+}
+
+bool ImageIndexIterator::hasNext() const
+{
+    return (mCurrentMip < mMipRange.end || mCurrentLayer < maxLayer());
+}
+
+}
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/libGLESv2/ImageIndex.h
@@ -0,0 +1,67 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ImageIndex.h: A helper struct for indexing into an Image array
+
+#ifndef LIBGLESV2_IMAGE_INDEX_H_
+#define LIBGLESV2_IMAGE_INDEX_H_
+
+#include "angle_gl.h"
+#include "common/mathutil.h"
+
+namespace gl
+{
+
+struct ImageIndex
+{
+    GLenum type;
+    GLint mipIndex;
+    GLint layerIndex;
+
+    ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn);
+    ImageIndex(const ImageIndex &other);
+    ImageIndex &operator=(const ImageIndex &other);
+
+    bool hasLayer() const { return layerIndex != ENTIRE_LEVEL; }
+
+    static ImageIndex Make2D(GLint mipIndex);
+    static ImageIndex MakeCube(GLenum target, GLint mipIndex);
+    static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex);
+    static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL);
+
+    static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1);
+};
+
+class ImageIndexIterator
+{
+  public:
+    static ImageIndexIterator Make2D(GLint minMip, GLint maxMip);
+    static ImageIndexIterator MakeCube(GLint minMip, GLint maxMip);
+    static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer);
+    static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts);
+
+    ImageIndex next();
+    ImageIndex current() const;
+    bool hasNext() const;
+
+  private:
+
+    ImageIndexIterator(GLenum type, const rx::Range<GLint> &mipRange,
+                       const rx::Range<GLint> &layerRange, const GLsizei *layerCounts);
+
+    GLint maxLayer() const;
+
+    GLenum mType;
+    rx::Range<GLint> mMipRange;
+    rx::Range<GLint> mLayerRange;
+    const GLsizei *mLayerCounts;
+    GLint mCurrentMip;
+    GLint mCurrentLayer;
+};
+
+}
+
+#endif // LIBGLESV2_IMAGE_INDEX_H_
--- a/gfx/angle/src/libGLESv2/Program.cpp
+++ b/gfx/angle/src/libGLESv2/Program.cpp
@@ -5,16 +5,17 @@
 //
 
 // Program.cpp: Implements the gl::Program class. Implements GL program objects
 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
 
 #include "libGLESv2/Program.h"
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/ResourceManager.h"
+#include "libGLESv2/renderer/Renderer.h"
 
 namespace gl
 {
 const char * const g_fakepath = "C:\\fakepath";
 
 AttributeBindings::AttributeBindings()
 {
 }
@@ -245,17 +246,17 @@ void Program::bindAttributeLocation(GLui
 // a list of uniforms
 bool Program::link(const Caps &caps)
 {
     unlink(false);
 
     mInfoLog.reset();
     resetUniformBlockBindings();
 
-    mProgramBinary.set(new ProgramBinary(mRenderer));
+    mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
     mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
                                    mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps);
 
     return mLinked;
 }
 
 int AttributeBindings::getAttributeBinding(const std::string &name) const
 {
@@ -303,18 +304,19 @@ ProgramBinary* Program::getProgramBinary
 }
 
 bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
 {
     unlink(false);
 
     mInfoLog.reset();
 
-    mProgramBinary.set(new ProgramBinary(mRenderer));
+    mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
     mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
+
     if (!mLinked)
     {
         mProgramBinary.set(NULL);
     }
 
     return mLinked;
 }
 
--- a/gfx/angle/src/libGLESv2/ProgramBinary.cpp
+++ b/gfx/angle/src/libGLESv2/ProgramBinary.cpp
@@ -5,69 +5,68 @@
 //
 
 // Program.cpp: Implements the gl::Program class. Implements GL program objects
 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
 
 #include "libGLESv2/BinaryStream.h"
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
 #include "libGLESv2/Renderbuffer.h"
 #include "libGLESv2/renderer/ShaderExecutable.h"
 
 #include "common/debug.h"
 #include "common/version.h"
 #include "common/utilities.h"
 #include "common/platform.h"
 
 #include "libGLESv2/main.h"
 #include "libGLESv2/Shader.h"
 #include "libGLESv2/Program.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/d3d/DynamicHLSL.h"
+#include "libGLESv2/renderer/ProgramImpl.h"
 #include "libGLESv2/renderer/d3d/ShaderD3D.h"
-#include "libGLESv2/renderer/d3d/VertexDataManager.h"
 #include "libGLESv2/Context.h"
 #include "libGLESv2/Buffer.h"
 #include "common/blocklayout.h"
 
 namespace gl
 {
 
 namespace
 {
 
-TextureType GetTextureType(GLenum samplerType)
+GLenum GetTextureType(GLenum samplerType)
 {
     switch (samplerType)
     {
       case GL_SAMPLER_2D:
       case GL_INT_SAMPLER_2D:
       case GL_UNSIGNED_INT_SAMPLER_2D:
       case GL_SAMPLER_2D_SHADOW:
-        return TEXTURE_2D;
+        return GL_TEXTURE_2D;
       case GL_SAMPLER_3D:
       case GL_INT_SAMPLER_3D:
       case GL_UNSIGNED_INT_SAMPLER_3D:
-        return TEXTURE_3D;
+        return GL_TEXTURE_3D;
       case GL_SAMPLER_CUBE:
       case GL_SAMPLER_CUBE_SHADOW:
-        return TEXTURE_CUBE;
+        return GL_TEXTURE_CUBE_MAP;
       case GL_INT_SAMPLER_CUBE:
       case GL_UNSIGNED_INT_SAMPLER_CUBE:
-        return TEXTURE_CUBE;
+        return GL_TEXTURE_CUBE_MAP;
       case GL_SAMPLER_2D_ARRAY:
       case GL_INT_SAMPLER_2D_ARRAY:
       case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
       case GL_SAMPLER_2D_ARRAY_SHADOW:
-        return TEXTURE_2D_ARRAY;
+        return GL_TEXTURE_2D_ARRAY;
       default: UNREACHABLE();
     }
 
-    return TEXTURE_2D;
+    return GL_TEXTURE_2D;
 }
 
 unsigned int ParseAndStripArrayIndex(std::string* name)
 {
     unsigned int subscript = GL_INVALID_INDEX;
 
     // Strip any trailing array operator and retrieve the subscript
     size_t open = name->find_last_of('[');
@@ -76,42 +75,16 @@ unsigned int ParseAndStripArrayIndex(std
     {
         subscript = atoi(name->substr(open + 1).c_str());
         name->erase(open);
     }
 
     return subscript;
 }
 
-void GetInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])
-{
-    size_t layoutIndex = 0;
-    for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
-    {
-        ASSERT(layoutIndex < MAX_VERTEX_ATTRIBS);
-
-        const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex];
-
-        if (shaderAttr.type != GL_NONE)
-        {
-            GLenum transposedType = TransposeMatrixType(shaderAttr.type);
-
-            for (size_t rowIndex = 0; static_cast<int>(rowIndex) < VariableRowCount(transposedType); rowIndex++, layoutIndex++)
-            {
-                VertexFormat *defaultFormat = &inputLayout[layoutIndex];
-
-                defaultFormat->mType = VariableComponentType(transposedType);
-                defaultFormat->mNormalized = false;
-                defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool
-                defaultFormat->mComponents = VariableColumnCount(transposedType);
-            }
-        }
-    }
-}
-
 bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
 {
     return var.isRowMajorLayout;
 }
 
 bool IsRowMajorLayout(const sh::ShaderVariable &var)
 {
     return false;
@@ -119,221 +92,61 @@ bool IsRowMajorLayout(const sh::ShaderVa
 
 }
 
 VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
     : name(name), element(element), index(index)
 {
 }
 
-ProgramBinary::VertexExecutable::VertexExecutable(const VertexFormat inputLayout[],
-                                                  const GLenum signature[],
-                                                  rx::ShaderExecutable *shaderExecutable)
-    : mShaderExecutable(shaderExecutable)
-{
-    for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
-    {
-        mInputs[attributeIndex] = inputLayout[attributeIndex];
-        mSignature[attributeIndex] = signature[attributeIndex];
-    }
-}
-
-ProgramBinary::VertexExecutable::~VertexExecutable()
-{
-    SafeDelete(mShaderExecutable);
-}
-
-bool ProgramBinary::VertexExecutable::matchesSignature(const GLenum signature[]) const
-{
-    for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
-    {
-        if (mSignature[attributeIndex] != signature[attributeIndex])
-        {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-ProgramBinary::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable)
-    : mOutputSignature(outputSignature),
-      mShaderExecutable(shaderExecutable)
-{
-}
-
-ProgramBinary::PixelExecutable::~PixelExecutable()
-{
-    SafeDelete(mShaderExecutable);
-}
-
 LinkedVarying::LinkedVarying()
 {
 }
 
 LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName,
                              unsigned int semanticIndex, unsigned int semanticIndexCount)
     : name(name), type(type), size(size), semanticName(semanticName), semanticIndex(semanticIndex), semanticIndexCount(semanticIndexCount)
 {
 }
 
 unsigned int ProgramBinary::mCurrentSerial = 1;
 
-ProgramBinary::ProgramBinary(rx::Renderer *renderer)
+ProgramBinary::ProgramBinary(rx::ProgramImpl *impl)
     : RefCountObject(0),
-      mRenderer(renderer),
-      mDynamicHLSL(NULL),
-      mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
-      mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
-      mGeometryExecutable(NULL),
+      mProgram(impl),
       mUsedVertexSamplerRange(0),
       mUsedPixelSamplerRange(0),
-      mUsesPointSize(false),
-      mShaderVersion(100),
       mDirtySamplerMapping(true),
-      mVertexUniformStorage(NULL),
-      mFragmentUniformStorage(NULL),
       mValidated(false),
       mSerial(issueSerial())
 {
+    ASSERT(impl);
+
     for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
     {
         mSemanticIndex[index] = -1;
     }
-
-    for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
-    {
-        mSamplersPS[index].active = false;
-    }
-
-    for (int index = 0; index < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++)
-    {
-        mSamplersVS[index].active = false;
-    }
-
-    mDynamicHLSL = new rx::DynamicHLSL(renderer);
 }
 
 ProgramBinary::~ProgramBinary()
 {
     reset();
-    SafeDelete(mDynamicHLSL);
+    SafeDelete(mProgram);
 }
 
 unsigned int ProgramBinary::getSerial() const
 {
     return mSerial;
 }
 
-int ProgramBinary::getShaderVersion() const
-{
-    return mShaderVersion;
-}
-
 unsigned int ProgramBinary::issueSerial()
 {
     return mCurrentSerial++;
 }
 
-rx::ShaderExecutable *ProgramBinary::getPixelExecutableForFramebuffer(const Framebuffer *fbo)
-{
-    std::vector<GLenum> outputs(IMPLEMENTATION_MAX_DRAW_BUFFERS);
-    for (size_t outputIndex = 0; outputIndex < IMPLEMENTATION_MAX_DRAW_BUFFERS; outputIndex++)
-    {
-        if (fbo->getColorbuffer(outputIndex) != NULL)
-        {
-            // Always output floats for now
-            outputs[outputIndex] = GL_FLOAT;
-        }
-        else
-        {
-            outputs[outputIndex] = GL_NONE;
-        }
-    }
-
-    return getPixelExecutableForOutputLayout(outputs);
-}
-
-rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature)
-{
-    for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
-    {
-        if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
-        {
-            return mPixelExecutables[executableIndex]->shaderExecutable();
-        }
-    }
-
-    std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth,
-                                                                                     outputSignature);
-
-    // Generate new pixel executable
-    InfoLog tempInfoLog;
-    rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL,
-                                                                           mTransformFeedbackLinkedVaryings,
-                                                                           (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
-                                                                           mPixelWorkarounds);
-
-    if (!pixelExecutable)
-    {
-        std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
-        tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
-        ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
-    }
-    else
-    {
-        mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
-    }
-
-    return pixelExecutable;
-}
-
-rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])
-{
-    GLenum signature[MAX_VERTEX_ATTRIBS];
-    mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
-
-    for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
-    {
-        if (mVertexExecutables[executableIndex]->matchesSignature(signature))
-        {
-            return mVertexExecutables[executableIndex]->shaderExecutable();
-        }
-    }
-
-    // Generate new dynamic layout with attribute conversions
-    std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes);
-
-    // Generate new vertex executable
-    InfoLog tempInfoLog;
-    rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL.c_str(),
-                                                                            rx::SHADER_VERTEX,
-                                                                            mTransformFeedbackLinkedVaryings,
-                                                                            (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
-                                                                            mVertexWorkarounds);
-
-    if (!vertexExecutable)
-    {
-        std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
-        tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
-        ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
-    }
-    else
-    {
-        mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable));
-    }
-
-    return vertexExecutable;
-}
-
-rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() const
-{
-    return mGeometryExecutable;
-}
-
 GLuint ProgramBinary::getAttributeLocation(const char *name)
 {
     if (name)
     {
         for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
         {
             if (mLinkedAttribute[index].name == std::string(name))
             {
@@ -364,49 +177,35 @@ GLint ProgramBinary::getUsedSamplerRange
       default:
         UNREACHABLE();
         return 0;
     }
 }
 
 bool ProgramBinary::usesPointSize() const
 {
-    return mUsesPointSize;
-}
-
-bool ProgramBinary::usesPointSpriteEmulation() const
-{
-    return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
+    return mProgram->usesPointSize();
 }
 
-bool ProgramBinary::usesGeometryShader() const
-{
-    return usesPointSpriteEmulation();
-}
-
-// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
-// index (0-15 for the pixel shader and 0-3 for the vertex shader).
 GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps)
 {
     GLint logicalTextureUnit = -1;
 
     switch (type)
     {
       case SAMPLER_PIXEL:
-        ASSERT(samplerIndex < ArraySize(mSamplersPS));
-
-        if (mSamplersPS[samplerIndex].active)
+        ASSERT(samplerIndex < caps.maxTextureImageUnits);
+        if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active)
         {
             logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
         }
         break;
       case SAMPLER_VERTEX:
-        ASSERT(samplerIndex < ArraySize(mSamplersVS));
-
-        if (mSamplersVS[samplerIndex].active)
+        ASSERT(samplerIndex < caps.maxVertexTextureImageUnits);
+        if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active)
         {
             logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
         }
         break;
       default: UNREACHABLE();
     }
 
     if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits))
@@ -414,32 +213,32 @@ GLint ProgramBinary::getSamplerMapping(S
         return logicalTextureUnit;
     }
 
     return -1;
 }
 
 // Returns the texture type for a given Direct3D 9 sampler type and
 // index (0-15 for the pixel shader and 0-3 for the vertex shader).
-TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
+GLenum ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
 {
     switch (type)
     {
       case SAMPLER_PIXEL:
-        ASSERT(samplerIndex < ArraySize(mSamplersPS));
+        ASSERT(samplerIndex < mSamplersPS.size());
         ASSERT(mSamplersPS[samplerIndex].active);
         return mSamplersPS[samplerIndex].textureType;
       case SAMPLER_VERTEX:
-        ASSERT(samplerIndex < ArraySize(mSamplersVS));
+        ASSERT(samplerIndex < mSamplersVS.size());
         ASSERT(mSamplersVS[samplerIndex].active);
         return mSamplersVS[samplerIndex].textureType;
       default: UNREACHABLE();
     }
 
-    return TEXTURE_2D;
+    return GL_TEXTURE_2D;
 }
 
 GLint ProgramBinary::getUniformLocation(std::string name)
 {
     unsigned int subscript = ParseAndStripArrayIndex(&name);
 
     unsigned int numUniforms = mUniformIndex.size();
     for (unsigned int location = 0; location < numUniforms; location++)
@@ -528,27 +327,27 @@ GLint ProgramBinary::getFragDataLocation
         }
     }
 
     return -1;
 }
 
 size_t ProgramBinary::getTransformFeedbackVaryingCount() const
 {
-    return mTransformFeedbackLinkedVaryings.size();
+    return mProgram->getTransformFeedbackLinkedVaryings().size();
 }
 
 const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const
 {
-    return mTransformFeedbackLinkedVaryings[idx];
+    return mProgram->getTransformFeedbackLinkedVaryings()[idx];
 }
 
 GLenum ProgramBinary::getTransformFeedbackBufferMode() const
 {
-    return mTransformFeedbackBufferMode;
+    return mProgram->getTransformFeedbackBufferMode();
 }
 
 template <typename T>
 static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
 {
     ASSERT(dest != NULL);
     ASSERT(dirtyFlag != NULL);
 
@@ -565,48 +364,74 @@ void ProgramBinary::setUniform(GLint loc
     LinkedUniform *targetUniform = getUniformByLocation(location);
 
     int elementCount = targetUniform->elementCount();
 
     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
 
     if (targetUniform->type == targetUniformType)
     {
-        T *target = (T*)targetUniform->data + mUniformIndex[location].element * 4;
+        T *target = reinterpret_cast<T*>(targetUniform->data) + mUniformIndex[location].element * 4;
 
         for (int i = 0; i < count; i++)
         {
+            T *dest = target + (i * 4);
+            const T *source = v + (i * components);
+
             for (int c = 0; c < components; c++)
             {
-                SetIfDirty(target + c, v[c], &targetUniform->dirty);
+                SetIfDirty(dest + c, source[c], &targetUniform->dirty);
             }
             for (int c = components; c < 4; c++)
             {
-                SetIfDirty(target + c, T(0), &targetUniform->dirty);
+                SetIfDirty(dest + c, T(0), &targetUniform->dirty);
             }
-            target += 4;
-            v += components;
         }
     }
     else if (targetUniform->type == targetBoolType)
     {
-        GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
+        GLint *boolParams = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
 
         for (int i = 0; i < count; i++)
         {
+            GLint *dest = boolParams + (i * 4);
+            const T *source = v + (i * components);
+
             for (int c = 0; c < components; c++)
             {
-                SetIfDirty(boolParams + c, (v[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
+                SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
             }
             for (int c = components; c < 4; c++)
             {
-                SetIfDirty(boolParams + c, GL_FALSE, &targetUniform->dirty);
+                SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
             }
-            boolParams += 4;
-            v += components;
+        }
+    }
+    else if (IsSampler(targetUniform->type))
+    {
+        ASSERT(targetUniformType == GL_INT);
+
+        GLint *target = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4;
+
+        bool wasDirty = targetUniform->dirty;
+
+        for (int i = 0; i < count; i++)
+        {
+            GLint *dest = target + (i * 4);
+            const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components);
+
+            SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
+            SetIfDirty(dest + 1, 0, &targetUniform->dirty);
+            SetIfDirty(dest + 2, 0, &targetUniform->dirty);
+            SetIfDirty(dest + 3, 0, &targetUniform->dirty);
+        }
+
+        if (!wasDirty && targetUniform->dirty)
+        {
+            mDirtySamplerMapping = true;
         }
     }
     else UNREACHABLE();
 }
 
 void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
 {
     setUniform(location, count, v, GL_FLOAT);
@@ -764,58 +589,17 @@ void ProgramBinary::setUniformMatrix3x4f
 
 void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
     setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
 }
 
 void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)
 {
-    LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
-    int elementCount = targetUniform->elementCount();
-
-    count = std::min(elementCount - (int)mUniformIndex[location].element, count);
-
-    if (targetUniform->type == GL_INT || IsSampler(targetUniform->type))
-    {
-        GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            SetIfDirty(target + 0, v[0], &targetUniform->dirty);
-            SetIfDirty(target + 1, 0, &targetUniform->dirty);
-            SetIfDirty(target + 2, 0, &targetUniform->dirty);
-            SetIfDirty(target + 3, 0, &targetUniform->dirty);
-            target += 4;
-            v += 1;
-        }
-    }
-    else if (targetUniform->type == GL_BOOL)
-    {
-        GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
-
-        for (int i = 0; i < count; i++)
-        {
-            SetIfDirty(boolParams + 0, (v[0] == 0) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
-            SetIfDirty(boolParams + 1, GL_FALSE, &targetUniform->dirty);
-            SetIfDirty(boolParams + 2, GL_FALSE, &targetUniform->dirty);
-            SetIfDirty(boolParams + 3, GL_FALSE, &targetUniform->dirty);
-            boolParams += 4;
-            v += 1;
-        }
-    }
-    else UNREACHABLE();
-
-    // Set a special flag if we change a sampler uniform
-    if (IsSampler(targetUniform->type) &&
-        (memcmp(targetUniform->data, v, sizeof(GLint)) != 0))
-    {
-        mDirtySamplerMapping = true;
-    }
+    setUniform(location, count, v, GL_INT);
 }
 
 void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v)
 {
     setUniform(location, count, v, GL_INT_VEC2);
 }
 
 void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v)
@@ -967,155 +751,127 @@ void ProgramBinary::updateSamplerMapping
                 if (targetUniform->isReferencedByFragmentShader())
                 {
                     unsigned int firstIndex = targetUniform->psRegisterIndex;
 
                     for (int i = 0; i < count; i++)
                     {
                         unsigned int samplerIndex = firstIndex + i;
 
-                        if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
+                        if (samplerIndex < mSamplersPS.size())
                         {
                             ASSERT(mSamplersPS[samplerIndex].active);
                             mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
                         }
                     }
                 }
 
                 if (targetUniform->isReferencedByVertexShader())
                 {
                     unsigned int firstIndex = targetUniform->vsRegisterIndex;
 
                     for (int i = 0; i < count; i++)
                     {
                         unsigned int samplerIndex = firstIndex + i;
 
-                        if (samplerIndex < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS)
+                        if (samplerIndex < mSamplersVS.size())
                         {
                             ASSERT(mSamplersVS[samplerIndex].active);
                             mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
                         }
                     }
                 }
             }
         }
     }
 }
 
 // Applies all the uniforms set for this program object to the renderer
-void ProgramBinary::applyUniforms()
+Error ProgramBinary::applyUniforms()
 {
     updateSamplerMapping();
 
-    mRenderer->applyUniforms(*this);
+    Error error = mProgram->applyUniforms(mUniforms);
+    if (error.isError())
+    {
+        return error;
+    }
 
     for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
     {
         mUniforms[uniformIndex]->dirty = false;
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const Caps &caps)
+Error ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const Caps &caps)
 {
-    const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL};
-    const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL};
-
-    const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
-    const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
-
     ASSERT(boundBuffers.size() == mUniformBlocks.size());
-
-    for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++)
-    {
-        UniformBlock *uniformBlock = getUniformBlockByIndex(uniformBlockIndex);
-        gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex];
-
-        ASSERT(uniformBlock && uniformBuffer);
-
-        if (uniformBuffer->getSize() < uniformBlock->dataSize)
-        {
-            // undefined behaviour
-            return false;
-        }
-
-        ASSERT(uniformBlock->isReferencedByVertexShader() || uniformBlock->isReferencedByFragmentShader());
-
-        if (uniformBlock->isReferencedByVertexShader())
-        {
-            unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
-            ASSERT(vertexUniformBuffers[registerIndex] == NULL);
-            ASSERT(registerIndex < caps.maxVertexUniformBlocks);
-            vertexUniformBuffers[registerIndex] = uniformBuffer;
-        }
-
-        if (uniformBlock->isReferencedByFragmentShader())
-        {
-            unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
-            ASSERT(fragmentUniformBuffers[registerIndex] == NULL);
-            ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
-            fragmentUniformBuffers[registerIndex] = uniformBuffer;
-        }
-    }
-
-    return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
+    return mProgram->applyUniformBuffers(mUniformBlocks, boundBuffers, caps);
 }
 
 bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader)
 {
-    rx::VertexShaderD3D *vertexShaderD3D = rx::VertexShaderD3D::makeVertexShaderD3D(vertexShader->getImplementation());
-    rx::FragmentShaderD3D *fragmentShaderD3D = rx::FragmentShaderD3D::makeFragmentShaderD3D(fragmentShader->getImplementation());
-
-    std::vector<PackedVarying> &fragmentVaryings = fragmentShaderD3D->getVaryings();
-    std::vector<PackedVarying> &vertexVaryings = vertexShaderD3D->getVaryings();
+    std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
+    std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings();
 
     for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++)
     {
         PackedVarying *input = &fragmentVaryings[fragVaryingIndex];
         bool matched = false;
 
+        // Built-in varyings obey special rules
+        if (input->isBuiltIn())
+        {
+            continue;
+        }
+
         for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++)
         {
             PackedVarying *output = &vertexVaryings[vertVaryingIndex];
             if (output->name == input->name)
             {
                 if (!linkValidateVaryings(infoLog, output->name, *input, *output))
                 {
                     return false;
                 }
 
                 output->registerIndex = input->registerIndex;
+                output->columnIndex = input->columnIndex;
 
                 matched = true;
                 break;
             }
         }
 
-        if (!matched)
+        // We permit unmatched, unreferenced varyings
+        if (!matched && input->staticUse)
         {
             infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
             return false;
         }
     }
 
     return true;
 }
 
 bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length)
 {
 #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
     return false;
 #else
-    ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
+    ASSERT(binaryFormat == mProgram->getBinaryFormat());
 
     reset();
 
     BinaryInputStream stream(binary, length);
 
-    int format = stream.readInt<int>();
-    if (format != GL_PROGRAM_BINARY_ANGLE)
+    GLenum format = stream.readInt<GLenum>();
+    if (format != mProgram->getBinaryFormat())
     {
         infoLog.append("Invalid program binary format.");
         return false;
     }
 
     int majorVersion = stream.readInt<int>();
     int minorVersion = stream.readInt<int>();
     if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
@@ -1138,41 +894,44 @@ bool ProgramBinary::load(InfoLog &infoLo
         infoLog.append("Mismatched compilation flags.");
         return false;
     }
 
     for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
     {
         stream.readInt(&mLinkedAttribute[i].type);
         stream.readString(&mLinkedAttribute[i].name);
-        stream.readInt(&mShaderAttributes[i].type);
-        stream.readString(&mShaderAttributes[i].name);
+        stream.readInt(&mProgram->getShaderAttributes()[i].type);
+        stream.readString(&mProgram->getShaderAttributes()[i].name);
         stream.readInt(&mSemanticIndex[i]);
     }
 
     initAttributesByLayout();
 
-    for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
+    const unsigned int psSamplerCount = stream.readInt<unsigned int>();
+    for (unsigned int i = 0; i < psSamplerCount; ++i)
     {
-        stream.readBool(&mSamplersPS[i].active);
-        stream.readInt(&mSamplersPS[i].logicalTextureUnit);
-        stream.readInt(&mSamplersPS[i].textureType);
+        Sampler sampler;
+        stream.readBool(&sampler.active);
+        stream.readInt(&sampler.logicalTextureUnit);
+        stream.readInt(&sampler.textureType);
+        mSamplersPS.push_back(sampler);
     }
-
-    for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
+    const unsigned int vsSamplerCount = stream.readInt<unsigned int>();
+    for (unsigned int i = 0; i < vsSamplerCount; ++i)
     {
-        stream.readBool(&mSamplersVS[i].active);
-        stream.readInt(&mSamplersVS[i].logicalTextureUnit);
-        stream.readInt(&mSamplersVS[i].textureType);
+        Sampler sampler;
+        stream.readBool(&sampler.active);
+        stream.readInt(&sampler.logicalTextureUnit);
+        stream.readInt(&sampler.textureType);
+        mSamplersVS.push_back(sampler);
     }
 
     stream.readInt(&mUsedVertexSamplerRange);
     stream.readInt(&mUsedPixelSamplerRange);
-    stream.readBool(&mUsesPointSize);
-    stream.readInt(&mShaderVersion);
 
     const unsigned int uniformCount = stream.readInt<unsigned int>();
     if (stream.error())
     {
         infoLog.append("Invalid program binary.");
         return false;
     }
 
@@ -1241,189 +1000,69 @@ bool ProgramBinary::load(InfoLog &infoLo
     mUniformIndex.resize(uniformIndexCount);
     for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++)
     {
         stream.readString(&mUniformIndex[uniformIndexIndex].name);
         stream.readInt(&mUniformIndex[uniformIndexIndex].element);
         stream.readInt(&mUniformIndex[uniformIndexIndex].index);
     }
 
-    stream.readInt(&mTransformFeedbackBufferMode);
-    const unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
-    mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
-    for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
-    {
-        LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
-
-        stream.readString(&varying.name);
-        stream.readInt(&varying.type);
-        stream.readInt(&varying.size);
-        stream.readString(&varying.semanticName);
-        stream.readInt(&varying.semanticIndex);
-        stream.readInt(&varying.semanticIndexCount);
-    }
-
-    stream.readString(&mVertexHLSL);
-
-    stream.readInt(&mVertexWorkarounds);
-
-    const unsigned int vertexShaderCount = stream.readInt<unsigned int>();
-    for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
+    if (!mProgram->load(infoLog, &stream))
     {
-        VertexFormat inputLayout[MAX_VERTEX_ATTRIBS];
-
-        for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++)
-        {
-            VertexFormat *vertexInput = &inputLayout[inputIndex];
-            stream.readInt(&vertexInput->mType);
-            stream.readInt(&vertexInput->mNormalized);
-            stream.readInt(&vertexInput->mComponents);
-            stream.readBool(&vertexInput->mPureInteger);
-        }
-
-        unsigned int vertexShaderSize = stream.readInt<unsigned int>();
-        const unsigned char *vertexShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset();
-        rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction),
-                                                                           vertexShaderSize, rx::SHADER_VERTEX,
-                                                                           mTransformFeedbackLinkedVaryings,
-                                                                           (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
-        if (!shaderExecutable)
-        {
-            infoLog.append("Could not create vertex shader.");
-            return false;
-        }
-
-        // generated converted input layout
-        GLenum signature[MAX_VERTEX_ATTRIBS];
-        mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
-
-        // add new binary
-        mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable));
-
-        stream.skip(vertexShaderSize);
-    }
-
-    stream.readString(&mPixelHLSL);
-    stream.readInt(&mPixelWorkarounds);
-    stream.readBool(&mUsesFragDepth);
-
-    const size_t pixelShaderKeySize = stream.readInt<unsigned int>();
-    mPixelShaderKey.resize(pixelShaderKeySize);
-    for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++)
-    {
-        stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
-        stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
-        stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
-        stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
-    }
-
-    const size_t pixelShaderCount = stream.readInt<unsigned int>();
-    for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
-    {
-        const size_t outputCount = stream.readInt<unsigned int>();
-        std::vector<GLenum> outputs(outputCount);
-        for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
-        {
-            stream.readInt(&outputs[outputIndex]);
-        }
-
-        const size_t pixelShaderSize = stream.readInt<unsigned int>();
-        const unsigned char *pixelShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset();
-        rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize,
-                                                                           rx::SHADER_PIXEL,
-                                                                           mTransformFeedbackLinkedVaryings,
-                                                                           (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
-        if (!shaderExecutable)
-        {
-            infoLog.append("Could not create pixel shader.");
-            return false;
-        }
-
-        // add new binary
-        mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
-
-        stream.skip(pixelShaderSize);
-    }
-
-    unsigned int geometryShaderSize = stream.readInt<unsigned int>();
-
-    if (geometryShaderSize > 0)
-    {
-        const char *geometryShaderFunction = (const char*) binary + stream.offset();
-        mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction),
-                                                        geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
-                                                        (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
-        if (!mGeometryExecutable)
-        {
-            infoLog.append("Could not create geometry shader.");
-            return false;
-        }
-        stream.skip(geometryShaderSize);
-    }
-
-    const char *ptr = (const char*) binary + stream.offset();
-
-    const GUID *binaryIdentifier = (const GUID *) ptr;
-    ptr += sizeof(GUID);
-
-    GUID identifier = mRenderer->getAdapterIdentifier();
-    if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0)
-    {
-        infoLog.append("Invalid program binary.");
         return false;
     }
 
-    initializeUniformStorage();
+    mProgram->initializeUniformStorage(mUniforms);
 
     return true;
 #endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
 }
 
 bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length)
 {
     if (binaryFormat)
     {
-        *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
+        *binaryFormat = mProgram->getBinaryFormat();
     }
 
     BinaryOutputStream stream;
 
-    stream.writeInt(GL_PROGRAM_BINARY_ANGLE);
+    stream.writeInt(mProgram->getBinaryFormat());
     stream.writeInt(ANGLE_MAJOR_VERSION);
     stream.writeInt(ANGLE_MINOR_VERSION);
     stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
     stream.writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
 
     for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
     {
         stream.writeInt(mLinkedAttribute[i].type);
         stream.writeString(mLinkedAttribute[i].name);
-        stream.writeInt(mShaderAttributes[i].type);
-        stream.writeString(mShaderAttributes[i].name);
+        stream.writeInt(mProgram->getShaderAttributes()[i].type);
+        stream.writeString(mProgram->getShaderAttributes()[i].name);
         stream.writeInt(mSemanticIndex[i]);
     }
 
-    for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
+    stream.writeInt(mSamplersPS.size());
+    for (unsigned int i = 0; i < mSamplersPS.size(); ++i)
     {
         stream.writeInt(mSamplersPS[i].active);
         stream.writeInt(mSamplersPS[i].logicalTextureUnit);
         stream.writeInt(mSamplersPS[i].textureType);
     }
 
-    for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
+    stream.writeInt(mSamplersVS.size());
+    for (unsigned int i = 0; i < mSamplersVS.size(); ++i)
     {
         stream.writeInt(mSamplersVS[i].active);
         stream.writeInt(mSamplersVS[i].logicalTextureUnit);
         stream.writeInt(mSamplersVS[i].textureType);
     }
 
     stream.writeInt(mUsedVertexSamplerRange);
     stream.writeInt(mUsedPixelSamplerRange);
-    stream.writeInt(mUsesPointSize);
-    stream.writeInt(mShaderVersion);
 
     stream.writeInt(mUniforms.size());
     for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
     {
         const LinkedUniform &uniform = *mUniforms[uniformIndex];
 
         stream.writeInt(uniform.type);
         stream.writeInt(uniform.precision);
@@ -1464,128 +1103,52 @@ bool ProgramBinary::save(GLenum *binaryF
     stream.writeInt(mUniformIndex.size());
     for (size_t i = 0; i < mUniformIndex.size(); ++i)
     {
         stream.writeString(mUniformIndex[i].name);
         stream.writeInt(mUniformIndex[i].element);
         stream.writeInt(mUniformIndex[i].index);
     }
 
-    stream.writeInt(mTransformFeedbackBufferMode);
-    stream.writeInt(mTransformFeedbackLinkedVaryings.size());
-    for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
+    if (!mProgram->save(&stream))
     {
-        const LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
-
-        stream.writeString(varying.name);
-        stream.writeInt(varying.type);
-        stream.writeInt(varying.size);
-        stream.writeString(varying.semanticName);
-        stream.writeInt(varying.semanticIndex);
-        stream.writeInt(varying.semanticIndexCount);
-    }
-
-    stream.writeString(mVertexHLSL);
-    stream.writeInt(mVertexWorkarounds);
-
-    stream.writeInt(mVertexExecutables.size());
-    for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
-    {
-        VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
-
-        for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
+        if (length)
         {
-            const VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex];
-            stream.writeInt(vertexInput.mType);
-            stream.writeInt(vertexInput.mNormalized);
-            stream.writeInt(vertexInput.mComponents);
-            stream.writeInt(vertexInput.mPureInteger);
+            *length = 0;
         }
 
-        size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
-        stream.writeInt(vertexShaderSize);
-
-        const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
-        stream.writeBytes(vertexBlob, vertexShaderSize);
-    }
-
-    stream.writeString(mPixelHLSL);
-    stream.writeInt(mPixelWorkarounds);
-    stream.writeInt(mUsesFragDepth);
-
-    stream.writeInt(mPixelShaderKey.size());
-    for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < mPixelShaderKey.size(); pixelShaderKeyIndex++)
-    {
-        const rx::PixelShaderOuputVariable &variable = mPixelShaderKey[pixelShaderKeyIndex];
-        stream.writeInt(variable.type);
-        stream.writeString(variable.name);
-        stream.writeString(variable.source);
-        stream.writeInt(variable.outputIndex);
+        return false;
     }
 
-    stream.writeInt(mPixelExecutables.size());
-    for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++)
-    {
-        PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
-
-        const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
-        stream.writeInt(outputs.size());
-        for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
-        {
-            stream.writeInt(outputs[outputIndex]);
-        }
-
-        size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
-        stream.writeInt(pixelShaderSize);
-
-        const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
-        stream.writeBytes(pixelBlob, pixelShaderSize);
-    }
-
-    size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
-    stream.writeInt(geometryShaderSize);
-
-    if (mGeometryExecutable != NULL && geometryShaderSize > 0)
-    {
-        const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
-        stream.writeBytes(geometryBlob, geometryShaderSize);
-    }
-
-    GUID identifier = mRenderer->getAdapterIdentifier();
-
     GLsizei streamLength = stream.length();
     const void *streamData = stream.data();
 
-    GLsizei totalLength = streamLength + sizeof(GUID);
-    if (totalLength > bufSize)
+    if (streamLength > bufSize)
     {
         if (length)
         {
             *length = 0;
         }
 
         return false;
     }
 
     if (binary)
     {
         char *ptr = (char*) binary;
 
         memcpy(ptr, streamData, streamLength);
         ptr += streamLength;
 
-        memcpy(ptr, &identifier, sizeof(GUID));
-        ptr += sizeof(GUID);
-
-        ASSERT(ptr - totalLength == binary);
+        ASSERT(ptr - streamLength == binary);
     }
 
     if (length)
     {
-        *length = totalLength;
+        *length = streamLength;
     }
 
     return true;
 }
 
 GLint ProgramBinary::getLength()
 {
     GLint length;
@@ -1611,55 +1174,33 @@ bool ProgramBinary::link(InfoLog &infoLo
     if (!vertexShader || !vertexShader->isCompiled())
     {
         return false;
     }
     ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
 
     reset();
 
-    mTransformFeedbackBufferMode = transformFeedbackBufferMode;
-
-    rx::VertexShaderD3D *vertexShaderD3D = rx::VertexShaderD3D::makeVertexShaderD3D(vertexShader->getImplementation());
-    rx::FragmentShaderD3D *fragmentShaderD3D = rx::FragmentShaderD3D::makeFragmentShaderD3D(fragmentShader->getImplementation());
-
-    mShaderVersion = vertexShaderD3D->getShaderVersion();
-
-    mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
-    mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
-
-    mVertexHLSL = vertexShaderD3D->getTranslatedSource();
-    mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
+    mSamplersPS.resize(caps.maxTextureImageUnits);
+    mSamplersVS.resize(caps.maxVertexTextureImageUnits);
 
-    // Map the varyings to the register file
-    rx::VaryingPacking packing = { NULL };
-    int registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings);
-
-    if (registers < 0)
-    {
-        return false;
-    }
+    rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
+    rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
 
-    if (!linkVaryings(infoLog, fragmentShader, vertexShader))
-    {
-        return false;
-    }
-
-    mUsesPointSize = vertexShaderD3D->usesPointSize();
+    int registers;
     std::vector<LinkedVarying> linkedVaryings;
-    if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, mPixelHLSL, mVertexHLSL,
-                                              fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
-                                              &linkedVaryings, &mOutputVariables, &mPixelShaderKey, &mUsesFragDepth))
+    if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode,
+                        &registers, &linkedVaryings, &mOutputVariables, caps))
     {
         return false;
     }
 
     bool success = true;
 
-    if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader))
+    if (!linkAttributes(infoLog, attributeBindings, vertexShader))
     {
         success = false;
     }
 
     if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps))
     {
         success = false;
     }
@@ -1675,69 +1216,54 @@ bool ProgramBinary::link(InfoLog &infoLo
     }
 
     if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps))
     {
         success = false;
     }
 
     if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
-                                               transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings, caps))
+                                               transformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), caps))
     {
         success = false;
     }
 
     if (success)
     {
-        VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS];
-        GetInputLayoutFromShader(vertexShaderD3D->getActiveAttributes(), defaultInputLayout);
-        rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout);
-
-        std::vector<GLenum> defaultPixelOutput(IMPLEMENTATION_MAX_DRAW_BUFFERS);
-        for (size_t i = 0; i < defaultPixelOutput.size(); i++)
-        {
-            defaultPixelOutput[i] = (i == 0) ? GL_FLOAT : GL_NONE;
-        }
-        rx::ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput);
-
-        if (usesGeometryShader())
-        {
-            std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D);
-            mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY,
-                                                                 mTransformFeedbackLinkedVaryings,
-                                                                 (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
-                                                                 rx::ANGLE_D3D_WORKAROUND_NONE);
-        }
-
-        if (!defaultVertexExecutable || !defaultPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
+        // TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called,
+        // however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling.
+        if (!mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers))
         {
             infoLog.append("Failed to create D3D shaders.");
             success = false;
             reset();
         }
     }
 
     return success;
 }
 
 // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
-bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader)
+bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader)
 {
-    rx::VertexShaderD3D *vertexShaderD3D = rx::VertexShaderD3D::makeVertexShaderD3D(vertexShader->getImplementation());
+    const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
 
     unsigned int usedLocations = 0;
-    const std::vector<sh::Attribute> &activeAttributes = vertexShaderD3D->getActiveAttributes();
+    const std::vector<sh::Attribute> &shaderAttributes = vertexShader->getActiveAttributes();
 
     // Link attributes that have a binding location
-    for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
+    for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
     {
-        const sh::Attribute &attribute = activeAttributes[attributeIndex];
+        const sh::Attribute &attribute = shaderAttributes[attributeIndex];
+
+        ASSERT(attribute.staticUse);
+
         const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
 
-        mShaderAttributes[attributeIndex] = attribute;
+        mProgram->getShaderAttributes()[attributeIndex] = attribute;
 
         if (location != -1)   // Set by glBindAttribLocation or by location layout qualifier
         {
             const int rows = VariableRegisterCount(attribute.type);
 
             if (rows + location > MAX_VERTEX_ATTRIBS)
             {
                 infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location);
@@ -1747,35 +1273,38 @@ bool ProgramBinary::linkAttributes(InfoL
 
             for (int row = 0; row < rows; row++)
             {
                 const int rowLocation = location + row;
                 sh::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation];
 
                 // In GLSL 3.00, attribute aliasing produces a link error
                 // In GLSL 1.00, attribute aliasing is allowed
-                if (mShaderVersion >= 300)
+                if (mProgram->getShaderVersion() >= 300)
                 {
                     if (!linkedAttribute.name.empty())
                     {
                         infoLog.append("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), linkedAttribute.name.c_str(), rowLocation);
                         return false;
                     }
                 }
 
                 linkedAttribute = attribute;
                 usedLocations |= 1 << rowLocation;
             }
         }
     }
 
     // Link attributes that don't have a binding location
-    for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
+    for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
     {
-        const sh::Attribute &attribute = activeAttributes[attributeIndex];
+        const sh::Attribute &attribute = shaderAttributes[attributeIndex];
+
+        ASSERT(attribute.staticUse);
+
         const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
 
         if (location == -1)   // Not set by glBindAttribLocation or by location layout qualifier
         {
             int rows = VariableRegisterCount(attribute.type);
             int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
 
             if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
@@ -1894,21 +1423,21 @@ bool ProgramBinary::linkValidateInterfac
         return false;
     }
 
     return true;
 }
 
 bool ProgramBinary::linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps)
 {
-    const rx::VertexShaderD3D *vertexShaderD3D = rx::VertexShaderD3D::makeVertexShaderD3D(vertexShader.getImplementation());
-    const rx::FragmentShaderD3D *fragmentShaderD3D = rx::FragmentShaderD3D::makeFragmentShaderD3D(fragmentShader.getImplementation());
+    const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader.getImplementation());
+    const rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader.getImplementation());
 
-    const std::vector<sh::Uniform> &vertexUniforms = vertexShaderD3D->getUniforms();
-    const std::vector<sh::Uniform> &fragmentUniforms = fragmentShaderD3D->getUniforms();
+    const std::vector<sh::Uniform> &vertexUniforms = vertexShader.getUniforms();
+    const std::vector<sh::Uniform> &fragmentUniforms = fragmentShader.getUniforms();
 
     // Check that uniforms defined in the vertex and fragment shaders are identical
     typedef std::map<std::string, const sh::Uniform*> UniformMap;
     UniformMap linkedUniforms;
 
     for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++)
     {
         const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex];
@@ -1928,31 +1457,39 @@ bool ProgramBinary::linkUniforms(InfoLog
                 return false;
             }
         }
     }
 
     for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++)
     {
         const sh::Uniform &uniform = vertexUniforms[uniformIndex];
-        defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name));
+
+        if (uniform.staticUse)
+        {
+            defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name));
+        }
     }
 
     for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++)
     {
         const sh::Uniform &uniform = fragmentUniforms[uniformIndex];
-        defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name));
+
+        if (uniform.staticUse)
+        {
+            defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name));
+        }
     }
 
     if (!indexUniforms(infoLog, caps))
     {
         return false;
     }
 
-    initializeUniformStorage();
+    mProgram->initializeUniformStorage(mUniforms);
 
     return true;
 }
 
 void ProgramBinary::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister)
 {
     ShShaderOutput outputType = rx::ShaderD3D::getCompilerOutputType(shader);
     sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
@@ -2028,43 +1565,43 @@ void ProgramBinary::defineUniform(GLenum
 bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps)
 {
     ASSERT(IsSampler(uniform.type));
     ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX);
 
     if (uniform.vsRegisterIndex != GL_INVALID_INDEX)
     {
         if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS,
-                            &mUsedVertexSamplerRange, caps.maxVertexTextureImageUnits))
+                            &mUsedVertexSamplerRange))
         {
             infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).",
-                           caps.maxVertexTextureImageUnits);
+                           mSamplersVS.size());
             return false;
         }
 
-        unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors;
+        unsigned int maxVertexVectors = mProgram->getReservedUniformVectors(GL_VERTEX_SHADER) + caps.maxVertexUniformVectors;
         if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors)
         {
             infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)",
                            caps.maxVertexUniformVectors);
             return false;
         }
     }
 
     if (uniform.psRegisterIndex != GL_INVALID_INDEX)
     {
         if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS,
-                            &mUsedPixelSamplerRange, caps.maxTextureImageUnits))
+                            &mUsedPixelSamplerRange))
         {
             infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).",
-                           caps.maxTextureImageUnits);
+                           mSamplersPS.size());
             return false;
         }
 
-        unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors;
+        unsigned int maxFragmentVectors = mProgram->getReservedUniformVectors(GL_FRAGMENT_SHADER) + caps.maxFragmentUniformVectors;
         if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors)
         {
             infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)",
                            caps.maxFragmentUniformVectors);
             return false;
         }
     }
 
@@ -2092,30 +1629,30 @@ bool ProgramBinary::indexUniforms(InfoLo
     }
 
     return true;
 }
 
 bool ProgramBinary::assignSamplers(unsigned int startSamplerIndex,
                                    GLenum samplerType,
                                    unsigned int samplerCount,
-                                   Sampler *outArray,
-                                   GLuint *usedRange,
-                                   unsigned int limit)
+                                   std::vector<Sampler> &outSamplers,
+                                   GLuint *outUsedRange)
 {
     unsigned int samplerIndex = startSamplerIndex;
 
     do
     {
-        if (samplerIndex < limit)
+        if (samplerIndex < outSamplers.size())
         {
-            outArray[samplerIndex].active = true;
-            outArray[samplerIndex].textureType = GetTextureType(samplerType);
-            outArray[samplerIndex].logicalTextureUnit = 0;
-            *usedRange = std::max(samplerIndex + 1, *usedRange);
+            Sampler& sampler = outSamplers[samplerIndex];
+            sampler.active = true;
+            sampler.textureType = GetTextureType(samplerType);
+            sampler.logicalTextureUnit = 0;
+            *outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
         }
         else
         {
             return false;
         }
 
         samplerIndex++;
     } while (samplerIndex < startSamplerIndex + samplerCount);
@@ -2166,21 +1703,18 @@ bool ProgramBinary::areMatchingInterface
         }
     }
 
     return true;
 }
 
 bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps)
 {
-    const rx::VertexShaderD3D *vertexShaderD3D = rx::VertexShaderD3D::makeVertexShaderD3D(vertexShader.getImplementation());
-    const rx::FragmentShaderD3D *fragmentShaderD3D = rx::FragmentShaderD3D::makeFragmentShaderD3D(fragmentShader.getImplementation());
-
-    const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShaderD3D->getInterfaceBlocks();
-    const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShaderD3D->getInterfaceBlocks();
+    const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks();
+    const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks();
 
     // Check that interface blocks defined in the vertex and fragment shaders are identical
     typedef std::map<std::string, const sh::InterfaceBlock*> UniformBlockMap;
     UniformBlockMap linkedUniformBlocks;
 
     for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
     {
         const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex];
@@ -2198,27 +1732,39 @@ bool ProgramBinary::linkUniformBlocks(In
             {
                 return false;
             }
         }
     }
 
     for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
     {
-        if (!defineUniformBlock(infoLog, vertexShader, vertexInterfaceBlocks[blockIndex], caps))
+        const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex];
+
+        // Note: shared and std140 layouts are always considered active
+        if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
         {
-            return false;
+            if (!defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps))
+            {
+                return false;
+            }
         }
     }
 
     for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
     {
-        if (!defineUniformBlock(infoLog, fragmentShader, fragmentInterfaceBlocks[blockIndex], caps))
+        const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex];
+
+        // Note: shared and std140 layouts are always considered active
+        if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
         {
-            return false;
+            if (!defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps))
+            {
+                return false;
+            }
         }
     }
 
     return true;
 }
 
 bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
                                                           const std::vector<std::string> &transformFeedbackVaryingNames,
@@ -2357,64 +1903,42 @@ bool ProgramBinary::defineUniformBlock(I
         else
         {
             UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize);
             newUniformBlock->memberUniformIndexes = blockUniformIndexes;
             mUniformBlocks.push_back(newUniformBlock);
         }
     }
 
-    // Assign registers to the uniform blocks
-    const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name);
-    const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize);
-    ASSERT(blockIndex != GL_INVALID_INDEX);
-    ASSERT(blockIndex + elementCount <= mUniformBlocks.size());
+    if (interfaceBlock.staticUse)
+    {
+        // Assign registers to the uniform blocks
+        const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name);
+        const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize);
+        ASSERT(blockIndex != GL_INVALID_INDEX);
+        ASSERT(blockIndex + elementCount <= mUniformBlocks.size());
 
-    unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name);
+        unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name);
 
-    for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++)
-    {
-        UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement];
-        ASSERT(uniformBlock->name == interfaceBlock.name);
+        for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++)
+        {
+            UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement];
+            ASSERT(uniformBlock->name == interfaceBlock.name);
 
-        if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(),
-                                        interfaceBlockRegister + uniformBlockElement, caps))
-        {
-            return false;
+            if (!mProgram->assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(),
+                                                      interfaceBlockRegister + uniformBlockElement, caps))
+            {
+                return false;
+            }
         }
     }
 
     return true;
 }
 
-bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps)
-{
-    if (shader == GL_VERTEX_SHADER)
-    {
-        uniformBlock->vsRegisterIndex = registerIndex;
-        if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks)
-        {
-            infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks);
-            return false;
-        }
-    }
-    else if (shader == GL_FRAGMENT_SHADER)
-    {
-        uniformBlock->psRegisterIndex = registerIndex;
-        if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks)
-        {
-            infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks);
-            return false;
-        }
-    }
-    else UNREACHABLE();
-
-    return true;
-}
-
 bool ProgramBinary::isValidated() const
 {
     return mValidated;
 }
 
 void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
 {
     // Skip over inactive attributes
@@ -2686,98 +2210,92 @@ void ProgramBinary::validate(InfoLog &in
 
 bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps)
 {
     // if any two active samplers in a program are of different types, but refer to the same
     // texture image unit, and this is the current program, then ValidateProgram will fail, and
     // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
     updateSamplerMapping();
 
-    const unsigned int maxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
-    TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
-
-    for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i)
-    {
-        textureUnitType[i] = TEXTURE_UNKNOWN;
-    }
+    std::vector<GLenum> textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE);
 
     for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
     {
         if (mSamplersPS[i].active)
         {
             unsigned int unit = mSamplersPS[i].logicalTextureUnit;
 
-            if (unit >= maxCombinedTextureImageUnits)
+            if (unit >= textureUnitTypes.size())
             {
                 if (infoLog)
                 {
-                    infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
+                    infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size());
                 }
 
                 return false;
             }
 
-            if (textureUnitType[unit] != TEXTURE_UNKNOWN)
+            if (textureUnitTypes[unit] != GL_NONE)
             {
-                if (mSamplersPS[i].textureType != textureUnitType[unit])
+                if (mSamplersPS[i].textureType != textureUnitTypes[unit])
                 {
                     if (infoLog)
                     {
                         infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
                     }
 
                     return false;
                 }
             }
             else
             {
-                textureUnitType[unit] = mSamplersPS[i].textureType;
+                textureUnitTypes[unit] = mSamplersPS[i].textureType;
             }
         }
     }
 
     for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
     {
         if (mSamplersVS[i].active)
         {
             unsigned int unit = mSamplersVS[i].logicalTextureUnit;
 
-            if (unit >= maxCombinedTextureImageUnits)
+            if (unit >= textureUnitTypes.size())
             {
                 if (infoLog)
                 {
-                    infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
+                    infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size());
                 }
 
                 return false;
             }
 
-            if (textureUnitType[unit] != TEXTURE_UNKNOWN)
+            if (textureUnitTypes[unit] != GL_NONE)
             {
-                if (mSamplersVS[i].textureType != textureUnitType[unit])
+                if (mSamplersVS[i].textureType != textureUnitTypes[unit])
                 {
                     if (infoLog)
                     {
                         infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
                     }
 
                     return false;
                 }
             }
             else
             {
-                textureUnitType[unit] = mSamplersVS[i].textureType;
+                textureUnitTypes[unit] = mSamplersVS[i].textureType;
             }
         }
     }
 
     return true;
 }
 
-ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D)
+ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D)
 {
 }
 
 struct AttributeSorter
 {
     AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS])
         : originalIndices(semanticIndices)
     {
@@ -2815,76 +2333,28 @@ void ProgramBinary::sortAttributesByLayo
     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
     {
         int oldIndex = mAttributesByLayout[i];
         sortedSemanticIndices[i] = mSemanticIndex[oldIndex];
         attributes[i] = oldTranslatedAttributes[oldIndex];
     }
 }
 
-void ProgramBinary::initializeUniformStorage()
-{
-    // Compute total default block size
-    unsigned int vertexRegisters = 0;
-    unsigned int fragmentRegisters = 0;
-    for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
-    {
-        const LinkedUniform &uniform = *mUniforms[uniformIndex];
-
-        if (!IsSampler(uniform.type))
-        {
-            if (uniform.isReferencedByVertexShader())
-            {
-                vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
-            }
-            if (uniform.isReferencedByFragmentShader())
-            {
-                fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
-            }
-        }
-    }
-
-    mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
-    mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
-}
-
 void ProgramBinary::reset()
 {
-    mVertexHLSL.clear();
-    mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
-    SafeDeleteContainer(mVertexExecutables);
-
-    mPixelHLSL.clear();
-    mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE;
-    mUsesFragDepth = false;
-    mPixelShaderKey.clear();
-    SafeDeleteContainer(mPixelExecutables);
-
-    SafeDelete(mGeometryExecutable);
+    mSamplersPS.clear();
+    mSamplersVS.clear();
 
-    mTransformFeedbackBufferMode = GL_NONE;
-    mTransformFeedbackLinkedVaryings.clear();
-
-    for (size_t i = 0; i < ArraySize(mSamplersPS); i++)
-    {
-        mSamplersPS[i] = Sampler();
-    }
-    for (size_t i = 0; i < ArraySize(mSamplersVS); i++)
-    {
-        mSamplersVS[i] = Sampler();
-    }
     mUsedVertexSamplerRange = 0;
     mUsedPixelSamplerRange = 0;
-    mUsesPointSize = false;
-    mShaderVersion = 0;
     mDirtySamplerMapping = true;
 
     SafeDeleteContainer(mUniforms);
     SafeDeleteContainer(mUniformBlocks);
     mUniformIndex.clear();
     mOutputVariables.clear();
-    SafeDelete(mVertexUniformStorage);
-    SafeDelete(mFragmentUniformStorage);
+
+    mProgram->reset();
 
     mValidated = false;
 }
 
 }
--- a/gfx/angle/src/libGLESv2/ProgramBinary.h
+++ b/gfx/angle/src/libGLESv2/ProgramBinary.h
@@ -37,16 +37,17 @@ class HLSLBlockEncoder;
 #include <vector>
 
 namespace rx
 {
 class ShaderExecutable;
 class Renderer;
 struct TranslatedAttribute;
 class UniformStorage;
+class ProgramImpl;
 }
 
 namespace gl
 {
 struct Caps;
 class Shader;
 class InfoLog;
 class AttributeBindings;
@@ -84,33 +85,29 @@ struct LinkedVarying
     unsigned int semanticIndex;
     unsigned int semanticIndexCount;
 };
 
 // This is the result of linking a program. It is the state that would be passed to ProgramBinary.
 class ProgramBinary : public RefCountObject
 {
   public:
-    explicit ProgramBinary(rx::Renderer *renderer);
+    explicit ProgramBinary(rx::ProgramImpl *impl);
     ~ProgramBinary();
 
-    rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo);
-    rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout);
-    rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]);
-    rx::ShaderExecutable *getGeometryExecutable() const;
+    rx::ProgramImpl *getImplementation() { return mProgram; }
+    const rx::ProgramImpl *getImplementation() const { return mProgram; }
 
     GLuint getAttributeLocation(const char *name);
     int getSemanticIndex(int attributeIndex);
 
     GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps);
-    TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex);
+    GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex);
     GLint getUsedSamplerRange(SamplerType type);
     bool usesPointSize() const;
-    bool usesPointSpriteEmulation() const;
-    bool usesGeometryShader() const;
 
     GLint getUniformLocation(std::string name);
     GLuint getUniformIndex(std::string name);
     GLuint getUniformBlockIndex(std::string name);
     void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
     void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
     void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
     void setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
@@ -132,18 +129,19 @@ class ProgramBinary : public RefCountObj
     void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 
     void getUniformfv(GLint location, GLfloat *params);
     void getUniformiv(GLint location, GLint *params);
     void getUniformuiv(GLint location, GLuint *params);
 
     void dirtyAllUniforms();
-    void applyUniforms();
-    bool applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps);
+
+    Error applyUniforms();
+    Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps);
 
     bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
     bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
     GLint getLength();
 
     bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
               const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps);
     void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
@@ -173,157 +171,96 @@ class ProgramBinary : public RefCountObj
     GLenum getTransformFeedbackBufferMode() const;
 
     void validate(InfoLog &infoLog, const Caps &caps);
     bool validateSamplers(InfoLog *infoLog, const Caps &caps);
     bool isValidated() const;
     void updateSamplerMapping();
 
     unsigned int getSerial() const;
-    int getShaderVersion() const;
 
     void initAttributesByLayout();
     void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const;
 
     const std::vector<LinkedUniform*> &getUniforms() const { return mUniforms; }
-    const rx::UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; }
-    const rx::UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
+
+    static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
 
     struct Sampler
     {
         Sampler();
 
         bool active;
         GLint logicalTextureUnit;
-        TextureType textureType;
+        GLenum textureType;
     };
 
     void reset();
 
-    bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader);
-    bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader);
+    bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader);
 
-    bool linkValidateVariablesBase(InfoLog &infoLog,
-                                   const std::string &variableName,
-                                   const sh::ShaderVariable &vertexVariable,
-                                   const sh::ShaderVariable &fragmentVariable,
-                                   bool validatePrecision);
+    static bool linkValidateVariablesBase(InfoLog &infoLog,
+                                          const std::string &variableName,
+                                          const sh::ShaderVariable &vertexVariable,
+                                          const sh::ShaderVariable &fragmentVariable,
+                                          bool validatePrecision);
 
-    bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
-    bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
-    bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
+    static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
+    static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
+    static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
     bool linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
     void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister);
     void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder);
     bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps);
     bool indexUniforms(InfoLog &infoLog, const Caps &caps);
     static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount,
-                               Sampler *outArray, GLuint *usedRange, unsigned int limit);
+                               std::vector<Sampler> &outSamplers, GLuint *outUsedRange);
     bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock);
     bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
     bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
                                                const std::vector<std::string> &transformFeedbackVaryingNames,
                                                GLenum transformFeedbackBufferMode,
                                                std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings,
                                                const Caps &caps) const;
     template <typename VarT>
     void defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
                                    sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
                                    bool inRowMajorLayout);
     bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps);
     bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps);
     void defineOutputVariables(Shader *fragmentShader);
-    void initializeUniformStorage();
 
     template <typename T>
     void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType);
 
     template <int cols, int rows>
     void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType);
 
     template <typename T>
     void getUniformv(GLint location, T *params, GLenum uniformType);
 
-    class VertexExecutable
-    {
-      public:
-        VertexExecutable(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS],
-                         const GLenum signature[MAX_VERTEX_ATTRIBS],
-                         rx::ShaderExecutable *shaderExecutable);
-        ~VertexExecutable();
-
-        bool matchesSignature(const GLenum convertedLayout[MAX_VERTEX_ATTRIBS]) const;
-
-        const VertexFormat *inputs() const { return mInputs; }
-        const GLenum *signature() const { return mSignature; }
-        rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
-
-      private:
-        VertexFormat mInputs[MAX_VERTEX_ATTRIBS];
-        GLenum mSignature[MAX_VERTEX_ATTRIBS];
-        rx::ShaderExecutable *mShaderExecutable;
-    };
-
-    class PixelExecutable
-    {
-      public:
-        PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable);
-        ~PixelExecutable();
-
-        // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers
-        bool matchesSignature(const std::vector<GLenum> &signature) const { return true; /* mOutputSignature == signature; */ }
-
-        const std::vector<GLenum> &outputSignature() const { return mOutputSignature; }
-        rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
-
-      private:
-        std::vector<GLenum> mOutputSignature;
-        rx::ShaderExecutable *mShaderExecutable;
-    };
-
-    rx::Renderer *const mRenderer;
-    rx::DynamicHLSL *mDynamicHLSL;
-
-    std::string mVertexHLSL;
-    rx::D3DWorkaroundType mVertexWorkarounds;
-    std::vector<VertexExecutable *> mVertexExecutables;
-
-    std::string mPixelHLSL;
-    rx::D3DWorkaroundType mPixelWorkarounds;
-    bool mUsesFragDepth;
-    std::vector<rx::PixelShaderOuputVariable> mPixelShaderKey;
-    std::vector<PixelExecutable *> mPixelExecutables;
-
-    rx::ShaderExecutable *mGeometryExecutable;
+    rx::ProgramImpl *mProgram;
 
     sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
-    sh::Attribute mShaderAttributes[MAX_VERTEX_ATTRIBS];
     int mSemanticIndex[MAX_VERTEX_ATTRIBS];
     int mAttributesByLayout[MAX_VERTEX_ATTRIBS];
 
-    GLenum mTransformFeedbackBufferMode;
-    std::vector<LinkedVarying> mTransformFeedbackLinkedVaryings;
-
-    Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS];
-    Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+    std::vector<Sampler> mSamplersPS;
+    std::vector<Sampler> mSamplersVS;
     GLuint mUsedVertexSamplerRange;
     GLuint mUsedPixelSamplerRange;
-    bool mUsesPointSize;
-    int mShaderVersion;
     bool mDirtySamplerMapping;
 
     std::vector<LinkedUniform*> mUniforms;
     std::vector<UniformBlock*> mUniformBlocks;
     std::vector<VariableLocation> mUniformIndex;
     std::map<int, VariableLocation> mOutputVariables;
-    rx::UniformStorage *mVertexUniformStorage;
-    rx::UniformStorage *mFragmentUniformStorage;
 
     bool mValidated;
 
     const unsigned int mSerial;
 
     static unsigned int issueSerial();
     static unsigned int mCurrentSerial;
 };
--- a/gfx/angle/src/libGLESv2/Query.cpp
+++ b/gfx/angle/src/libGLESv2/Query.cpp
@@ -14,46 +14,37 @@ namespace gl
 Query::Query(rx::QueryImpl *impl, GLuint id)
     : RefCountObject(id),
       mQuery(impl)
 {
 }
 
 Query::~Query()
 {
-    delete mQuery;
+    SafeDelete(mQuery);
 }
 
-void Query::begin()
+Error Query::begin()
 {
-    // TODO: Rather than keeping track of whether the query was successfully
-    // created via a boolean in the GL-level Query object, we should probably
-    // use the error system to track these failed creations at the context level,
-    // and reset the active query ID for the target to 0 upon failure.
-    mStarted = mQuery->begin();
+    return mQuery->begin();
 }
 
-void Query::end()
+Error Query::end()
 {
-    mQuery->end();
+    return mQuery->end();
 }
 
-GLuint Query::getResult()
+Error Query::getResult(GLuint *params)
 {
-    return mQuery->getResult();
+    return mQuery->getResult(params);
 }
 
-GLboolean Query::isResultAvailable()
+Error Query::isResultAvailable(GLuint *available)
 {
-    return mQuery->isResultAvailable();
+    return mQuery->isResultAvailable(available);
 }
 
 GLenum Query::getType() const
 {
     return mQuery->getType();
 }
 
-bool Query::isStarted() const
-{
-    return mStarted;
 }
-
-}
--- a/gfx/angle/src/libGLESv2/Query.h
+++ b/gfx/angle/src/libGLESv2/Query.h
@@ -4,16 +4,17 @@
 // found in the LICENSE file.
 //
 
 // Query.h: Defines the gl::Query class
 
 #ifndef LIBGLESV2_QUERY_H_
 #define LIBGLESV2_QUERY_H_
 
+#include "libGLESv2/Error.h"
 #include "common/angleutils.h"
 #include "common/RefCountObject.h"
 
 #include "angle_gl.h"
 
 namespace rx
 {
 class QueryImpl;
@@ -23,28 +24,25 @@ namespace gl
 {
 
 class Query : public RefCountObject
 {
   public:
     Query(rx::QueryImpl *impl, GLuint id);
     virtual ~Query();
 
-    void begin();
-    void end();
+    Error begin();
+    Error end();
 
-    GLuint getResult();
-    GLboolean isResultAvailable();
+    Error getResult(GLuint *params);
+    Error isResultAvailable(GLuint *available);
 
     GLenum getType() const;
-    bool isStarted() const;
 
   private:
     DISALLOW_COPY_AND_ASSIGN(Query);
 
-    bool mStarted;
-
     rx::QueryImpl *mQuery;
 };
 
 }
 
 #endif   // LIBGLESV2_QUERY_H_
--- a/gfx/angle/src/libGLESv2/Renderbuffer.cpp
+++ b/gfx/angle/src/libGLESv2/Renderbuffer.cpp
@@ -120,21 +120,16 @@ RenderbufferStorage::~RenderbufferStorag
 {
 }
 
 rx::RenderTarget *RenderbufferStorage::getRenderTarget()
 {
     return NULL;
 }
 
-rx::RenderTarget *RenderbufferStorage::getDepthStencil()
-{
-    return NULL;
-}
-
 GLsizei RenderbufferStorage::getWidth() const
 {
     return mWidth;
 }
 
 GLsizei RenderbufferStorage::getHeight() const
 {
     return mHeight;
@@ -155,17 +150,17 @@ GLsizei RenderbufferStorage::getSamples(
     return mSamples;
 }
 
 unsigned int RenderbufferStorage::getSerial() const
 {
     return mSerial;
 }
 
-unsigned int RenderbufferStorage::issueSerials(GLuint count)
+unsigned int RenderbufferStorage::issueSerials(unsigned int count)
 {
     unsigned int firstSerial = mCurrentSerial;
     mCurrentSerial += count;
     return firstSerial;
 }
 
 bool RenderbufferStorage::isTexture() const
 {
--- a/gfx/angle/src/libGLESv2/Renderbuffer.h
+++ b/gfx/angle/src/libGLESv2/Renderbuffer.h
@@ -66,30 +66,29 @@ class Renderbuffer : public RefCountObje
 class RenderbufferStorage
 {
   public:
     RenderbufferStorage();
 
     virtual ~RenderbufferStorage() = 0;
 
     virtual rx::RenderTarget *getRenderTarget();
-    virtual rx::RenderTarget *getDepthStencil();
 
     virtual GLsizei getWidth() const;
     virtual GLsizei getHeight() const;
     virtual GLenum getInternalFormat() const;
     virtual GLenum getActualFormat() const;
     virtual GLsizei getSamples() const;
 
     virtual unsigned int getSerial() const;
 
     virtual bool isTexture() const;
     virtual unsigned int getTextureSerial() const;
 
-    static unsigned int issueSerials(GLuint count);
+    static unsigned int issueSerials(unsigned int count);
 
   protected:
     GLsizei mWidth;
     GLsizei mHeight;
     GLenum mInternalFormat;
     GLenum mActualFormat;
     GLsizei mSamples;
 
--- a/gfx/angle/src/libGLESv2/ResourceManager.cpp
+++ b/gfx/angle/src/libGLESv2/ResourceManager.cpp
@@ -361,35 +361,35 @@ void ResourceManager::checkBufferAllocat
     if (buffer != 0 && !getBuffer(buffer))
     {
         Buffer *bufferObject = new Buffer(mRenderer->createBuffer(), buffer);
         mBufferMap[buffer] = bufferObject;
         bufferObject->addRef();
     }
 }
 
-void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type)
+void ResourceManager::checkTextureAllocation(GLuint texture, GLenum type)
 {
     if (!getTexture(texture) && texture != 0)
     {
         Texture *textureObject;
 
-        if (type == TEXTURE_2D)
+        if (type == GL_TEXTURE_2D)
         {
             textureObject = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), texture);
         }
-        else if (type == TEXTURE_CUBE)
+        else if (type == GL_TEXTURE_CUBE_MAP)
         {
             textureObject = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), texture);
         }
-        else if (type == TEXTURE_3D)
+        else if (type == GL_TEXTURE_3D)
         {
             textureObject = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), texture);
         }
-        else if (type == TEXTURE_2D_ARRAY)
+        else if (type == GL_TEXTURE_2D_ARRAY)
         {
             textureObject = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), texture);
         }
         else
         {
             UNREACHABLE();
             return;
         }
--- a/gfx/angle/src/libGLESv2/ResourceManager.h
+++ b/gfx/angle/src/libGLESv2/ResourceManager.h
@@ -60,21 +60,21 @@ class ResourceManager
 
     Buffer *getBuffer(GLuint handle);
     Shader *getShader(GLuint handle);
     Program *getProgram(GLuint handle);
     Texture *getTexture(GLuint handle);
     Renderbuffer *getRenderbuffer(GLuint handle);
     Sampler *getSampler(GLuint handle);
     FenceSync *getFenceSync(GLuint handle);
-    
+
     void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
 
     void checkBufferAllocation(unsigned int buffer);
-    void checkTextureAllocation(GLuint texture, TextureType type);
+    void checkTextureAllocation(GLuint texture, GLenum type);
     void checkRenderbufferAllocation(GLuint renderbuffer);
     void checkSamplerAllocation(GLuint sampler);
 
     bool isSampler(GLuint sampler);
 
   private:
     DISALLOW_COPY_AND_ASSIGN(ResourceManager);
 
--- a/gfx/angle/src/libGLESv2/Shader.cpp
+++ b/gfx/angle/src/libGLESv2/Shader.cpp
@@ -27,16 +27,17 @@ Shader::Shader(ResourceManager *manager,
     : mShader(impl),
       mType(type),
       mHandle(handle),
       mResourceManager(manager),
       mRefCount(0),
       mDeleteStatus(false),
       mCompiled(false)
 {
+    ASSERT(impl);
 }
 
 Shader::~Shader()
 {
 }
 
 GLuint Shader::getHandle() const
 {
@@ -146,9 +147,59 @@ bool Shader::isFlaggedForDeletion() cons
     return mDeleteStatus;
 }
 
 void Shader::flagForDeletion()
 {
     mDeleteStatus = true;
 }
 
+const std::vector<gl::PackedVarying> &Shader::getVaryings() const
+{
+    return mShader->getVaryings();
 }
+
+const std::vector<sh::Uniform> &Shader::getUniforms() const
+{
+    return mShader->getUniforms();
+}
+
+const std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() const
+{
+    return mShader->getInterfaceBlocks();
+}
+
+const std::vector<sh::Attribute> &Shader::getActiveAttributes() const
+{
+    return mShader->getActiveAttributes();
+}
+
+const std::vector<sh::Attribute> &Shader::getActiveOutputVariables() const
+{
+    return mShader->getActiveOutputVariables();
+}
+
+std::vector<gl::PackedVarying> &Shader::getVaryings()
+{
+    return mShader->getVaryings();
+}
+
+std::vector<sh::Uniform> &Shader::getUniforms()
+{
+    return mShader->getUniforms();
+}
+
+std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks()
+{
+    return mShader->getInterfaceBlocks();
+}
+
+std::vector<sh::Attribute> &Shader::getActiveAttributes()
+{
+    return mShader->getActiveAttributes();
+}
+
+std::vector<sh::Attribute> &Shader::getActiveOutputVariables()
+{
+    return mShader->getActiveOutputVariables();
+}
+
+}
--- a/gfx/angle/src/libGLESv2/Shader.h
+++ b/gfx/angle/src/libGLESv2/Shader.h
@@ -30,23 +30,26 @@ class ShaderImpl;
 
 namespace gl
 {
 class ResourceManager;
 
 struct PackedVarying : public sh::Varying
 {
     unsigned int registerIndex; // Assigned during link
+    unsigned int columnIndex; // Assigned during link, defaults to 0
 
     PackedVarying(const sh::Varying &varying)
       : sh::Varying(varying),
-        registerIndex(GL_INVALID_INDEX)
+        registerIndex(GL_INVALID_INDEX),
+        columnIndex(0)
     {}
 
     bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; }
+    bool isBuiltIn() const { return name.compare(0, 3, "gl_") == 0; }
 
     void resetRegisterAssignment()
     {
         registerIndex = GL_INVALID_INDEX;
     }
 };
 
 class Shader
@@ -75,16 +78,28 @@ class Shader
     bool isCompiled() const { return mCompiled; }
 
     void addRef();
     void release();
     unsigned int getRefCount() const;
     bool isFlaggedForDeletion() const;
     void flagForDeletion();
 
+    const std::vector<gl::PackedVarying> &getVaryings() const;
+    const std::vector<sh::Uniform> &getUniforms() const;
+    const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const;
+    const std::vector<sh::Attribute> &getActiveAttributes() const;
+    const std::vector<sh::Attribute> &getActiveOutputVariables() const;
+
+    std::vector<gl::PackedVarying> &getVaryings();
+    std::vector<sh::Uniform> &getUniforms();
+    std::vector<sh::InterfaceBlock> &getInterfaceBlocks();
+    std::vector<sh::Attribute> &getActiveAttributes();
+    std::vector<sh::Attribute> &getActiveOutputVariables();
+
   private:
     DISALLOW_COPY_AND_ASSIGN(Shader);
 
     static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer);
 
     rx::ShaderImpl *mShader;
     const GLuint mHandle;
     const GLenum mType;
--- a/gfx/angle/src/libGLESv2/State.cpp
+++ b/gfx/angle/src/libGLESv2/State.cpp
@@ -4,27 +4,38 @@
 // found in the LICENSE file.
 //
 
 // State.cpp: Implements the State class, encapsulating raw GL state.
 
 #include "libGLESv2/State.h"
 
 #include "libGLESv2/Context.h"
+#include "libGLESv2/Caps.h"
 #include "libGLESv2/VertexArray.h"
 #include "libGLESv2/Query.h"
 #include "libGLESv2/Framebuffer.h"
 #include "libGLESv2/FramebufferAttachment.h"
 #include "libGLESv2/renderer/RenderTarget.h"
 #include "libGLESv2/formatutils.h"
 
 namespace gl
 {
+
 State::State()
 {
+}
+
+State::~State()
+{
+    reset();
+}
+
+void State::initialize(const Caps& caps, GLuint clientVersion)
+{
     mContext = NULL;
 
     setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
     mDepthClearValue = 1.0f;
     mStencilClearValue = 0;
 
     mRasterizer.rasterizerDiscard = false;
@@ -60,17 +71,17 @@ State::State()
     mDepthStencil.depthTest = false;
     mDepthStencil.depthFunc = GL_LESS;
     mDepthStencil.depthMask = true;
     mDepthStencil.stencilTest = false;
     mDepthStencil.stencilFunc = GL_ALWAYS;
     mDepthStencil.stencilMask = -1;
     mDepthStencil.stencilWritemask = -1;
     mDepthStencil.stencilBackFunc = GL_ALWAYS;
-    mDepthStencil.stencilBackMask = - 1;
+    mDepthStencil.stencilBackMask = -1;
     mDepthStencil.stencilBackWritemask = -1;
     mDepthStencil.stencilFail = GL_KEEP;
     mDepthStencil.stencilPassDepthFail = GL_KEEP;
     mDepthStencil.stencilPassDepthPass = GL_KEEP;
     mDepthStencil.stencilBackFail = GL_KEEP;
     mDepthStencil.stencilBackPassDepthFail = GL_KEEP;
     mDepthStencil.stencilBackPassDepthPass = GL_KEEP;
 
@@ -92,49 +103,60 @@ State::State()
     mNearZ = 0.0f;
     mFarZ = 1.0f;
 
     mBlend.colorMaskRed = true;
     mBlend.colorMaskGreen = true;
     mBlend.colorMaskBlue = true;
     mBlend.colorMaskAlpha = true;
 
+    mActiveSampler = 0;
+
     const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f };
     for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++)
     {
         mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
     }
 
-    for (unsigned int textureUnit = 0; textureUnit < ArraySize(mSamplers); textureUnit++)
+    mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits);
+    mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits);
+    if (clientVersion >= 3)
     {
-        mSamplers[textureUnit].set(NULL);
+        // TODO: These could also be enabled via extension
+        mSamplerTextures[GL_TEXTURE_2D_ARRAY].resize(caps.maxCombinedTextureImageUnits);
+        mSamplerTextures[GL_TEXTURE_3D].resize(caps.maxCombinedTextureImageUnits);
     }
 
-    mActiveSampler = 0;
+    mSamplers.resize(caps.maxCombinedTextureImageUnits);
 
     mActiveQueries[GL_ANY_SAMPLES_PASSED].set(NULL);
     mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL);
     mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(NULL);
 
     mCurrentProgramId = 0;
     mCurrentProgramBinary.set(NULL);
 
     mReadFramebuffer = NULL;
     mDrawFramebuffer = NULL;
 }
 
-State::~State()
+void State::reset()
 {
-    for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
+    for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++)
     {
-        for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
+        TextureBindingVector &textureVector = bindingVec->second;
+        for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
         {
-            mSamplerTexture[type][sampler].set(NULL);
+            textureVector[textureIdx].set(NULL);
         }
     }
+    for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++)
+    {
+        mSamplers[samplerIdx].set(NULL);
+    }
 
     const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f };
     for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++)
     {
         mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
     }
 
     mArrayBuffer.set(NULL);
@@ -239,25 +261,18 @@ ClearParameters State::getClearParameter
             clearParams.clearDepth = true;
         }
     }
 
     if (mask & GL_STENCIL_BUFFER_BIT)
     {
         if (framebufferObject->getStencilbuffer() != NULL)
         {
-            rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getRenderTarget();
-            if (!depthStencil)
-            {
-                ERR("Depth stencil pointer unexpectedly null.");
-                ClearParameters nullClearParam = { 0 };
-                return nullClearParam;
-            }
-
-            if (GetInternalFormatInfo(depthStencil->getActualFormat()).stencilBits > 0)
+            GLenum stencilActualFormat = framebufferObject->getStencilbuffer()->getActualFormat();
+            if (GetInternalFormatInfo(stencilActualFormat).stencilBits > 0)
             {
                 clearParams.clearStencil = true;
             }
         }
     }
 
     return clearParams;
 }
@@ -585,56 +600,58 @@ void State::setActiveSampler(unsigned in
     mActiveSampler = active;
 }
 
 unsigned int State::getActiveSampler() const
 {
     return mActiveSampler;
 }
 
-void State::setSamplerTexture(TextureType type, Texture *texture)
+void State::setSamplerTexture(GLenum type, Texture *texture)
 {
-    mSamplerTexture[type][mActiveSampler].set(texture);
+    mSamplerTextures[type][mActiveSampler].set(texture);
 }
 
-Texture *State::getSamplerTexture(unsigned int sampler, TextureType type) const
+Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const
 {
-    GLuint texid = mSamplerTexture[type][sampler].id();
+    const BindingPointer<Texture>& binding = mSamplerTextures.at(type)[sampler];
 
-    if (texid == 0)   // Special case: 0 refers to default textures held by Context
+    if (binding.id() == 0)   // Special case: 0 refers to default textures held by Context
     {
         return NULL;
     }
 
-    return mSamplerTexture[type][sampler].get();
+    return binding.get();
 }
 
-GLuint State::getSamplerTextureId(unsigned int sampler, TextureType type) const
+GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const
 {
-    return mSamplerTexture[type][sampler].id();
+    return mSamplerTextures.at(type)[sampler].id();
 }
 
 void State::detachTexture(GLuint texture)
 {
     // Textures have a detach method on State rather than a simple
     // removeBinding, because the zero/null texture objects are managed
     // separately, and don't have to go through the Context's maps or
     // the ResourceManager.
 
     // [OpenGL ES 2.0.24] section 3.8 page 84:
     // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
     // rebound to texture object zero
 
-    for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
+    for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++)
     {
-        for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
+        TextureBindingVector &textureVector = bindingVec->second;
+        for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
         {
-            if (mSamplerTexture[type][sampler].id() == texture)
+            BindingPointer<Texture> &binding = textureVector[textureIdx];
+            if (binding.id() == texture)
             {
-                mSamplerTexture[type][sampler].set(NULL);
+                binding.set(NULL);
             }
         }
     }
 
     // [OpenGL ES 2.0.24] section 4.4 page 112:
     // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
     // as if Texture2DAttachment had been called, with a texture of 0, for each attachment point to which this
     // image was attached in the currently bound framebuffer.
@@ -652,36 +669,37 @@ void State::detachTexture(GLuint texture
 
 void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler)
 {
     mSamplers[textureUnit].set(sampler);
 }
 
 GLuint State::getSamplerId(GLuint textureUnit) const
 {
-    ASSERT(textureUnit < ArraySize(mSamplers));
+    ASSERT(textureUnit < mSamplers.size());
     return mSamplers[textureUnit].id();
 }
 
 Sampler *State::getSampler(GLuint textureUnit) const
 {
     return mSamplers[textureUnit].get();
 }
 
 void State::detachSampler(GLuint sampler)
 {
     // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124:
     // If a sampler object that is currently bound to one or more texture units is
     // deleted, it is as though BindSampler is called once for each texture unit to
     // which the sampler is bound, with unit set to the texture unit and sampler set to zero.
-    for (unsigned int textureUnit = 0; textureUnit < ArraySize(mSamplers); textureUnit++)
+    for (size_t textureUnit = 0; textureUnit < mSamplers.size(); textureUnit++)
     {
-        if (mSamplers[textureUnit].id() == sampler)
+        BindingPointer<Sampler> &samplerBinding = mSamplers[textureUnit];
+        if (samplerBinding.id() == sampler)
         {
-            mSamplers[textureUnit].set(NULL);
+            samplerBinding.set(NULL);
         }
     }
 }
 
 void State::setRenderbufferBinding(Renderbuffer *renderbuffer)
 {
     mRenderbuffer.set(renderbuffer);
 }
@@ -1310,29 +1328,29 @@ void State::getIntegerv(GLenum pname, GL
             else
             {
                 *params = 0;
             }
         }
         break;
       case GL_TEXTURE_BINDING_2D:
         ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
-        *params = mSamplerTexture[TEXTURE_2D][mActiveSampler].id();
+        *params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id();
         break;
       case GL_TEXTURE_BINDING_CUBE_MAP:
         ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
-        *params = mSamplerTexture[TEXTURE_CUBE][mActiveSampler].id();
+        *params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id();
         break;
       case GL_TEXTURE_BINDING_3D:
         ASSERT(mActiveSampler <mContext->getCaps().maxCombinedTextureImageUnits);
-        *params = mSamplerTexture[TEXTURE_3D][mActiveSampler].id();
+        *params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id();
         break;
       case GL_TEXTURE_BINDING_2D_ARRAY:
         ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
-        *params = mSamplerTexture[TEXTURE_2D_ARRAY][mActiveSampler].id();
+        *params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id();
         break;
       case GL_UNIFORM_BUFFER_BINDING:
         *params = mGenericUniformBuffer.id();
         break;
       case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
         *params = mGenericTransformFeedbackBuffer.id();
         break;
       case GL_COPY_READ_BUFFER_BINDING:
--- a/gfx/angle/src/libGLESv2/State.h
+++ b/gfx/angle/src/libGLESv2/State.h
@@ -19,23 +19,27 @@
 #include "libGLESv2/Program.h"
 #include "libGLESv2/Sampler.h"
 
 namespace gl
 {
 class Query;
 class VertexArray;
 class Context;
+struct Caps;
 
 class State
 {
   public:
     State();
     ~State();
 
+    void initialize(const Caps& caps, GLuint clientVersion);
+    void reset();
+
     void setContext(Context *context) { mContext = context; }
 
     // State chunk getters
     const RasterizerState &getRasterizerState() const;
     const BlendState &getBlendState() const;
     const DepthStencilState &getDepthStencilState() const;
 
     // Clear behavior setters & state parameter block generation function
@@ -121,19 +125,19 @@ class State
 
     // Viewport state setter/getter
     void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
     const Rectangle &getViewport() const;
 
     // Texture binding & active texture unit manipulation
     void setActiveSampler(unsigned int active);
     unsigned int getActiveSampler() const;
-    void setSamplerTexture(TextureType type, Texture *texture);
-    Texture *getSamplerTexture(unsigned int sampler, TextureType type) const;
-    GLuint getSamplerTextureId(unsigned int sampler, TextureType type) const;
+    void setSamplerTexture(GLenum type, Texture *texture);
+    Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
+    GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const;
     void detachTexture(GLuint texture);
 
     // Sampler object binding manipulation
     void setSamplerBinding(GLuint textureUnit, Sampler *sampler);
     GLuint getSamplerId(GLuint textureUnit) const;
     Sampler *getSampler(GLuint textureUnit) const;
     void detachSampler(GLuint sampler);
 
@@ -267,29 +271,35 @@ class State
 
     GLenum mGenerateMipmapHint;
     GLenum mFragmentShaderDerivativeHint;
 
     Rectangle mViewport;
     float mNearZ;
     float mFarZ;
 
-    unsigned int mActiveSampler;   // Active texture unit selector - GL_TEXTURE0
     BindingPointer<Buffer> mArrayBuffer;
     Framebuffer *mReadFramebuffer;
     Framebuffer *mDrawFramebuffer;
     BindingPointer<Renderbuffer> mRenderbuffer;
     GLuint mCurrentProgramId;
     BindingPointer<ProgramBinary> mCurrentProgramBinary;
 
     VertexAttribCurrentValueData mVertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib
     VertexArray *mVertexArray;
 
-    BindingPointer<Texture> mSamplerTexture[TEXTURE_TYPE_COUNT][IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
-    BindingPointer<Sampler> mSamplers[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
+    // Texture and sampler bindings
+    size_t mActiveSampler;   // Active texture unit selector - GL_TEXTURE0
+
+    typedef std::vector< BindingPointer<Texture> > TextureBindingVector;
+    typedef std::map<GLenum, TextureBindingVector> TextureBindingMap;
+    TextureBindingMap mSamplerTextures;
+
+    typedef std::vector< BindingPointer<Sampler> > SamplerBindingVector;
+    SamplerBindingVector mSamplers;
 
     typedef std::map< GLenum, BindingPointer<Query> > ActiveQueryMap;
     ActiveQueryMap mActiveQueries;
 
     BindingPointer<Buffer> mGenericUniformBuffer;
     OffsetBindingPointer<Buffer> mUniformBuffers[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
 
     BindingPointer<TransformFeedback> mTransformFeedback;
--- a/gfx/angle/src/libGLESv2/Texture.cpp
+++ b/gfx/angle/src/libGLESv2/Texture.cpp
@@ -7,19 +7,19 @@
 // Texture.cpp: Implements the gl::Texture class and its derived classes
 // Texture2D and TextureCubeMap. Implements GL texture objects and related
 // functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
 
 #include "libGLESv2/Texture.h"
 #include "libGLESv2/main.h"
 #include "libGLESv2/Context.h"
 #include "libGLESv2/formatutils.h"
+#include "libGLESv2/ImageIndex.h"
 #include "libGLESv2/Renderbuffer.h"
 #include "libGLESv2/renderer/Image.h"
-#include "libGLESv2/renderer/RenderTarget.h"
 #include "libGLESv2/renderer/d3d/TextureStorage.h"
 
 #include "libEGL/Surface.h"
 
 #include "common/mathutil.h"
 #include "common/utilities.h"
 
 namespace gl
@@ -72,17 +72,17 @@ void Texture::setUsage(GLenum usage)
     getImplementation()->setUsage(usage);
 }
 
 void Texture::getSamplerStateWithNativeOffset(SamplerState *sampler)
 {
     *sampler = mSamplerState;
 
     // Offset the effective base level by the texture storage's top level
-    rx::TextureStorageInterface *texture = getNativeTexture();
+    rx::TextureStorage *texture = getNativeTexture();
     int topLevel = texture ? texture->getTopLevel() : 0;
     sampler->baseLevel = topLevel + mSamplerState.baseLevel;
 }
 
 GLenum Texture::getUsage() const
 {
     return mUsage;
 }
@@ -109,45 +109,69 @@ GLint Texture::getBaseLevelDepth() const
 // where in the base of 2D array textures and cube maps there are several. Don't use
 // the base level image for anything except querying texture format and size.
 GLenum Texture::getBaseLevelInternalFormat() const
 {
     const rx::Image *baseImage = getBaseLevelImage();
     return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
 }
 
-rx::TextureStorageInterface *Texture::getNativeTexture()
+GLsizei Texture::getWidth(const ImageIndex &index) const
+{
+    rx::Image *image = mTexture->getImage(index);
+    return image->getWidth();
+}
+
+GLsizei Texture::getHeight(const ImageIndex &index) const
+{
+    rx::Image *image = mTexture->getImage(index);
+    return image->getHeight();
+}
+
+GLenum Texture::getInternalFormat(const ImageIndex &index) const
+{
+    rx::Image *image = mTexture->getImage(index);
+    return image->getInternalFormat();
+}
+
+GLenum Texture::getActualFormat(const ImageIndex &index) const
+{
+    rx::Image *image = mTexture->getImage(index);
+    return image->getActualFormat();
+}
+
+rx::TextureStorage *Texture::getNativeTexture()
 {
     return getImplementation()->getNativeTexture();
 }
 
 void Texture::generateMipmaps()
 {
     getImplementation()->generateMipmaps();
 }
 
 void Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
 {
     getImplementation()->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
 }
 
 unsigned int Texture::getTextureSerial()
 {
-    rx::TextureStorageInterface *texture = getNativeTexture();
+    rx::TextureStorage *texture = getNativeTexture();
     return texture ? texture->getTextureSerial() : 0;
 }
 
 bool Texture::isImmutable() const
 {
     return mImmutable;
 }
 
 int Texture::immutableLevelCount()
 {
-    return (mImmutable ? getNativeTexture()->getStorageInstance()->getLevelCount() : 0);
+    return (mImmutable ? getNativeTexture()->getLevelCount() : 0);
 }
 
 int Texture::mipLevels() const
 {
     return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
 }
 
 const rx::Image *Texture::getBaseLevelImage() const
@@ -197,21 +221,21 @@ GLenum Texture2D::getInternalFormat(GLin
 GLenum Texture2D::getActualFormat(GLint level) const
 {
     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
         return mTexture->getImage(level, 0)->getActualFormat();
     else
         return GL_NONE;
 }
 
-void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
     releaseTexImage();
 
-    mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels);
+    return mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels);
 }
 
 void Texture2D::bindTexImage(egl::Surface *surface)
 {
     releaseTexImage();
 
     mTexture->bindTexImage(surface);
 
@@ -225,31 +249,33 @@ void Texture2D::releaseTexImage()
     {
         mSurface->setBoundTexture(NULL);
         mSurface = NULL;
 
         mTexture->releaseTexImage();
     }
 }
 
-void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
+Error Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize,
+                                    const void *pixels)
 {
     releaseTexImage();
 
-    mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, pixels);
+    return mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, pixels);
 }
 
-void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
+    return mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
 }
 
-void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
+Error Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                                    GLenum format, GLsizei imageSize, const void *pixels)
 {
-    mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels);
+    return mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels);
 }
 
 void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
 {
     releaseTexImage();
 
     mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source);
 }
@@ -337,26 +363,16 @@ bool Texture2D::isDepth(GLint level) con
 
 void Texture2D::generateMipmaps()
 {
     releaseTexImage();
 
     mTexture->generateMipmaps();
 }
 
-unsigned int Texture2D::getRenderTargetSerial(GLint level)
-{
-    return mTexture->getRenderTargetSerial(level, 0);
-}
-
-rx::RenderTarget *Texture2D::getRenderTarget(GLint level)
-{
-    return mTexture->getRenderTarget(level, 0);
-}
-
 // Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
 bool Texture2D::isMipmapComplete() const
 {
     int levelCount = mipLevels();
 
     for (int level = 0; level < levelCount; level++)
     {
         if (!isLevelComplete(level))
@@ -448,59 +464,37 @@ GLenum TextureCubeMap::getInternalFormat
 GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const
 {
     if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
         return mTexture->getImage(level, targetToLayerIndex(target))->getActualFormat();
     else
         return GL_NONE;
 }
 
-void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error TextureCubeMap::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels);
+    return mTexture->setImage(target, level, width, height, 1, internalFormat, format, type, unpack, pixels);
 }
 
-void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
-    mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels);
-}
-
-void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height,
+                                         GLsizei imageSize, const void *pixels)
 {
-    mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels);
-}
-
-void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
-    mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels);
+    return mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, pixels);
 }
 
-void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels);
-}
-
-void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
-    mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels);
+    return mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
 }
 
-void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
-{
-    mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, pixels);
-}
-
-void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset,
+                                         GLsizei width, GLsizei height, GLenum format,
+                                         GLsizei imageSize, const void *pixels)
 {
-    mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
-}
-
-void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
-{
-    mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels);
+    return mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels);
 }
 
 // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
 bool TextureCubeMap::isCubeComplete() const
 {
     int    baseWidth  = getBaseLevelWidth();
     int    baseHeight = getBaseLevelHeight();
     GLenum baseFormat = getBaseLevelInternalFormat();
@@ -580,21 +574,16 @@ bool TextureCubeMap::isSamplerComplete(c
         {
             return false;
         }
     }
 
     return true;
 }
 
-unsigned int TextureCubeMap::getRenderTargetSerial(GLenum target, GLint level)
-{
-    return mTexture->getRenderTargetSerial(level, targetToLayerIndex(target));
-}
-
 int TextureCubeMap::targetToLayerIndex(GLenum target)
 {
     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
     META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
     META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
 
@@ -607,21 +596,16 @@ GLenum TextureCubeMap::layerIndexToTarge
     META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
     META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
     META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
 
     return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
 }
 
-rx::RenderTarget *TextureCubeMap::getRenderTarget(GLenum target, GLint level)
-{
-    return mTexture->getRenderTarget(level, targetToLayerIndex(target));
-}
-
 bool TextureCubeMap::isMipmapComplete() const
 {
     if (isImmutable())
     {
         return true;
     }
 
     if (!isCubeComplete())
@@ -725,34 +709,37 @@ bool Texture3D::isCompressed(GLint level
     return GetInternalFormatInfo(getInternalFormat(level)).compressed;
 }
 
 bool Texture3D::isDepth(GLint level) const
 {
     return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
-void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels);
+    return mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels);
+}
+
+Error Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth,
+                                    GLsizei imageSize, const void *pixels)
+{
+    return mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, pixels);
 }
 
-void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+Error Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, pixels);
+    return mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
 }
 
-void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                    GLsizei width, GLsizei height, GLsizei depth, GLenum format,
+                                    GLsizei imageSize, const void *pixels)
 {
-    mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
-}
-
-void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
-{
-    mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
+    return mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
 }
 
 void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
 {
     mImmutable = true;
 
     mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth);
 }
@@ -776,27 +763,16 @@ bool Texture3D::isSamplerComplete(const 
     if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
     {
         return false;
     }
 
     return true;
 }
 
-unsigned int Texture3D::getRenderTargetSerial(GLint level, GLint layer)
-{
-    return mTexture->getRenderTargetSerial(level, layer);
-}
-
-
-rx::RenderTarget *Texture3D::getRenderTarget(GLint level, GLint layer)
-{
-    return mTexture->getRenderTarget(level, layer);
-}
-
 bool Texture3D::isMipmapComplete() const
 {
     int levelCount = mipLevels();
 
     for (int level = 0; level < levelCount; level++)
     {
         if (!isLevelComplete(level))
         {
@@ -894,34 +870,37 @@ bool Texture2DArray::isCompressed(GLint 
     return GetInternalFormatInfo(getInternalFormat(level)).compressed;
 }
 
 bool Texture2DArray::isDepth(GLint level) const
 {
     return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
-void Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels);
+    return mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels);
+}
+
+Error Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth,
+                                         GLsizei imageSize, const void *pixels)
+{
+    return mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, pixels);
 }
 
-void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
+Error Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
 {
-    mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, pixels);
+    return mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
 }
 
-void Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
+Error Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                                         GLsizei width, GLsizei height, GLsizei depth, GLenum format,
+                                         GLsizei imageSize, const void *pixels)
 {
-    mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
-}
-
-void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
-{
-    mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
+    return mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
 }
 
 void Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
 {
     mImmutable = true;
 
     mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth);
 }
@@ -945,26 +924,16 @@ bool Texture2DArray::isSamplerComplete(c
     if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
     {
         return false;
     }
 
     return true;
 }
 
-unsigned int Texture2DArray::getRenderTargetSerial(GLint level, GLint layer)
-{
-    return mTexture->getRenderTargetSerial(level, layer);
-}
-
-rx::RenderTarget *Texture2DArray::getRenderTarget(GLint level, GLint layer)
-{
-    return mTexture->getRenderTarget(level, layer);
-}
-
 bool Texture2DArray::isMipmapComplete() const
 {
     int levelCount = mipLevels();
 
     for (int level = 1; level < levelCount; level++)
     {
         if (!isLevelComplete(level))
         {
--- a/gfx/angle/src/libGLESv2/Texture.h
+++ b/gfx/angle/src/libGLESv2/Texture.h
@@ -25,24 +25,24 @@
 namespace egl
 {
 class Surface;
 }
 
 namespace rx
 {
 class TextureStorageInterface;
-class RenderTarget;
 class Image;
 }
 
 namespace gl
 {
 class Framebuffer;
 class FramebufferAttachment;
+struct ImageIndex;
 
 bool IsMipmapFiltered(const gl::SamplerState &samplerState);
 
 class Texture : public RefCountObject
 {
   public:
     Texture(rx::TextureImpl *impl, GLuint id, GLenum target);
 
@@ -57,19 +57,24 @@ class Texture : public RefCountObject
     void setUsage(GLenum usage);
     GLenum getUsage() const;
 
     GLint getBaseLevelWidth() const;
     GLint getBaseLevelHeight() const;
     GLint getBaseLevelDepth() const;
     GLenum getBaseLevelInternalFormat() const;
 
+    GLsizei getWidth(const ImageIndex &index) const;
+    GLsizei getHeight(const ImageIndex &index) const;
+    GLenum getInternalFormat(const ImageIndex &index) const;
+    GLenum getActualFormat(const ImageIndex &index) const;
+
     virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const = 0;
 
-    rx::TextureStorageInterface *getNativeTexture();
+    rx::TextureStorage *getNativeTexture();
 
     virtual void generateMipmaps();
     virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
 
     unsigned int getTextureSerial();
 
     bool isImmutable() const;
     int immutableLevelCount();
@@ -106,35 +111,29 @@ class Texture2D : public Texture
 
     GLsizei getWidth(GLint level) const;
     GLsizei getHeight(GLint level) const;
     GLenum getInternalFormat(GLint level) const;
     GLenum getActualFormat(GLint level) const;
     bool isCompressed(GLint level) const;
     bool isDepth(GLint level) const;
 
-    void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
-    void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
+    Error setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
+    Error subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
     void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
     void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
 
     virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
     virtual void bindTexImage(egl::Surface *surface);
     virtual void releaseTexImage();
 
     virtual void generateMipmaps();
 
-    unsigned int getRenderTargetSerial(GLint level);
-
-  protected:
-    friend class Texture2DAttachment;
-    rx::RenderTarget *getRenderTarget(GLint level);
-
   private:
     DISALLOW_COPY_AND_ASSIGN(Texture2D);
 
     bool isMipmapComplete() const;
     bool isLevelComplete(int level) const;
 
     egl::Surface *mSurface;
 };
@@ -148,43 +147,30 @@ class TextureCubeMap : public Texture
 
     GLsizei getWidth(GLenum target, GLint level) const;
     GLsizei getHeight(GLenum target, GLint level) const;
     GLenum getInternalFormat(GLenum target, GLint level) const;
     GLenum getActualFormat(GLenum target, GLint level) const;
     bool isCompressed(GLenum target, GLint level) const;
     bool isDepth(GLenum target, GLint level) const;
 
-    void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-
-    void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
-
-    void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
+    Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
+    Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
     void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
     void storage(GLsizei levels, GLenum internalformat, GLsizei size);
 
     virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
 
     bool isCubeComplete() const;
 
-    unsigned int getRenderTargetSerial(GLenum target, GLint level);
-
     static int targetToLayerIndex(GLenum target);
     static GLenum layerIndexToTarget(GLint layer);
 
-  protected:
-    friend class TextureCubeMapAttachment;
-    rx::RenderTarget *getRenderTarget(GLenum target, GLint level);
-
   private:
     DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
 
     bool isMipmapComplete() const;
     bool isFaceLevelComplete(int faceIndex, int level) const;
 };
 
 class Texture3D : public Texture
@@ -197,30 +183,24 @@ class Texture3D : public Texture
     GLsizei getWidth(GLint level) const;
     GLsizei getHeight(GLint level) const;
     GLsizei getDepth(GLint level) const;
     GLenum getInternalFormat(GLint level) const;
     GLenum getActualFormat(GLint level) const;
     bool isCompressed(GLint level) const;
     bool isDepth(GLint level) const;
 
-    void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
-    void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
+    Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
+    Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
     void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 
     virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
 
-    unsigned int getRenderTargetSerial(GLint level, GLint layer);
-
-  protected:
-    friend class Texture3DAttachment;
-    rx::RenderTarget *getRenderTarget(GLint level, GLint layer);
-
   private:
     DISALLOW_COPY_AND_ASSIGN(Texture3D);
 
     bool isMipmapComplete() const;
     bool isLevelComplete(int level) const;
 };
 
 class Texture2DArray : public Texture
@@ -233,30 +213,24 @@ class Texture2DArray : public Texture
     GLsizei getWidth(GLint level) const;
     GLsizei getHeight(GLint level) const;
     GLsizei getLayers(GLint level) const;
     GLenum getInternalFormat(GLint level) const;
     GLenum getActualFormat(GLint level) const;
     bool isCompressed(GLint level) const;
     bool isDepth(GLint level) const;
 
-    void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
-    void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
-    void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
+    Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
+    Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
+    Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
     void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 
     virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
 
-    unsigned int getRenderTargetSerial(GLint level, GLint layer);
-
-  protected:
-    friend class Texture2DArrayAttachment;
-    rx::RenderTarget *getRenderTarget(GLint level, GLint layer);
-
   private:
     DISALLOW_COPY_AND_ASSIGN(Texture2DArray);
 
     bool isMipmapComplete() const;
     bool isLevelComplete(int level) const;
 };
 
 }
--- a/gfx/angle/src/libGLESv2/VertexArray.h
+++ b/gfx/angle/src/libGLESv2/VertexArray.h
@@ -39,17 +39,17 @@ class VertexArray
 
     const VertexAttribute& getVertexAttribute(size_t attributeIndex) const;
     void detachBuffer(GLuint bufferName);
     void setVertexAttribDivisor(GLuint index, GLuint divisor);
     void enableAttribute(unsigned int attributeIndex, bool enabledState);
     void setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type,
                            bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
 
-    const VertexAttribute* getVertexAttributes() const { return mVertexAttributes.data(); }
+    const VertexAttribute* getVertexAttributes() const { return &mVertexAttributes[0]; }
     Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); }
     void setElementArrayBuffer(Buffer *buffer);
     GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); }
     size_t getMaxAttribs() const { return mVertexAttributes.size(); }
 
   private:
     GLuint mId;
 
--- a/gfx/angle/src/libGLESv2/angletypes.h
+++ b/gfx/angle/src/libGLESv2/angletypes.h
@@ -14,27 +14,16 @@
 
 namespace gl
 {
 class Buffer;
 class ProgramBinary;
 struct VertexAttribute;
 struct VertexAttribCurrentValueData;
 
-enum TextureType
-{
-    TEXTURE_2D,
-    TEXTURE_CUBE,
-    TEXTURE_3D,
-    TEXTURE_2D_ARRAY,
-
-    TEXTURE_TYPE_COUNT,
-    TEXTURE_UNKNOWN
-};
-
 enum SamplerType
 {
     SAMPLER_PIXEL,
     SAMPLER_VERTEX
 };
 
 template <typename T>
 struct Color
@@ -256,18 +245,11 @@ namespace rx
 enum VertexConversionType
 {
     VERTEX_CONVERT_NONE = 0,
     VERTEX_CONVERT_CPU  = 1,
     VERTEX_CONVERT_GPU  = 2,
     VERTEX_CONVERT_BOTH = 3
 };
 
-enum D3DWorkaroundType
-{
-    ANGLE_D3D_WORKAROUND_NONE,
-    ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION,
-    ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION
-};
-
 }
 
 #endif // LIBGLESV2_ANGLETYPES_H_
--- a/gfx/angle/src/libGLESv2/formatutils.cpp
+++ b/gfx/angle/src/libGLESv2/formatutils.cpp
@@ -207,50 +207,57 @@ static bool UnimplementedSupport(GLuint,
 }
 
 static bool NeverSupported(GLuint, const Extensions &)
 {
     return false;
 }
 
 template <GLuint minCoreGLVersion>
-static bool RequireESVersion(GLuint clientVersion, const Extensions &)
+static bool RequireES(GLuint clientVersion, const Extensions &)
 {
     return clientVersion >= minCoreGLVersion;
 }
 
 // Pointer to a boolean memeber of the Extensions struct
 typedef bool(Extensions::*ExtensionBool);
 
 // Check support for a single extension
 template <ExtensionBool bool1>
-static bool RequireExtension(GLuint, const Extensions & extensions)
+static bool RequireExt(GLuint, const Extensions & extensions)
 {
     return extensions.*bool1;
 }
 
 // Check for a minimum client version or a single extension
 template <GLuint minCoreGLVersion, ExtensionBool bool1>
-static bool RequireESVersionOrExtension(GLuint clientVersion, const Extensions &extensions)
+static bool RequireESOrExt(GLuint clientVersion, const Extensions &extensions)
 {
     return clientVersion >= minCoreGLVersion || extensions.*bool1;
 }
 
 // Check for a minimum client version or two extensions
 template <GLuint minCoreGLVersion, ExtensionBool bool1, ExtensionBool bool2>
-static bool RequireESVersionOrExtensions(GLuint clientVersion, const Extensions &extensions)
+static bool RequireESOrExtAndExt(GLuint clientVersion, const Extensions &extensions)
 {
-    return clientVersion >= minCoreGLVersion || (extensions.*bool1 || extensions.*bool2);
+    return clientVersion >= minCoreGLVersion || (extensions.*bool1 && extensions.*bool2);
+}
+
+// Check for a minimum client version or at least one of two extensions
+template <GLuint minCoreGLVersion, ExtensionBool bool1, ExtensionBool bool2>
+static bool RequireESOrExtOrExt(GLuint clientVersion, const Extensions &extensions)
+{
+    return clientVersion >= minCoreGLVersion || extensions.*bool1 || extensions.*bool2;
 }
 
 // Check support for two extensions
 template <ExtensionBool bool1, ExtensionBool bool2>
-static bool RequireExtensions(GLuint, const Extensions &extensions)
+static bool RequireExtAndExt(GLuint, const Extensions &extensions)
 {
-    return extensions.*bool1 || extensions.*bool2;
+    return extensions.*bool1 && extensions.*bool2;
 }
 
 InternalFormat::InternalFormat()
     : redBits(0),
       greenBits(0),
       blueBits(0),
       luminanceBits(0),
       alphaBits(0),
@@ -375,139 +382,139 @@ typedef std::map<GLenum, InternalFormat>
 
 static InternalFormatInfoMap BuildInternalFormatInfoMap()
 {
     InternalFormatInfoMap map;
 
     // From ES 3.0.1 spec, table 3.12
     map.insert(InternalFormatInfoPair(GL_NONE,              InternalFormat()));
 
-    //                               | Internal format     |          | R | G | B | A |S | Format         | Type                           | Component type        | SRGB | Texture supported                                    | Renderable      | Filterable    |
-    map.insert(InternalFormatInfoPair(GL_R8,                RGBAFormat( 8,  0,  0,  0, 0, GL_RED,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::textureRG>, AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_R8_SNORM,          RGBAFormat( 8,  0,  0,  0, 0, GL_RED,          GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireESVersion<3>,                                    NeverSupported,  AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RG8,               RGBAFormat( 8,  8,  0,  0, 0, GL_RG,           GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::textureRG>, AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RG8_SNORM,         RGBAFormat( 8,  8,  0,  0, 0, GL_RG,           GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireESVersion<3>,                                    NeverSupported,  AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB8,              RGBAFormat( 8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::rgb8rgba8>, AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB8_SNORM,        RGBAFormat( 8,  8,  8,  0, 0, GL_RGB,          GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireESVersion<3>,                                    NeverSupported,  AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB565,            RGBAFormat( 5,  6,  5,  0, 0, GL_RGB,          GL_UNSIGNED_SHORT_5_6_5,         GL_UNSIGNED_NORMALIZED, false, RequireESVersion<2>,                                    AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGBA4,             RGBAFormat( 4,  4,  4,  4, 0, GL_RGBA,         GL_UNSIGNED_SHORT_4_4_4_4,       GL_UNSIGNED_NORMALIZED, false, RequireESVersion<2>,                                    AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB5_A1,           RGBAFormat( 5,  5,  5,  1, 0, GL_RGBA,         GL_UNSIGNED_SHORT_5_5_5_1,       GL_UNSIGNED_NORMALIZED, false, RequireESVersion<2>,                                    AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGBA8,             RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::rgb8rgba8>, AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGBA8_SNORM,       RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA,         GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireESVersion<3>,                                    NeverSupported,  AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB10_A2,          RGBAFormat(10, 10, 10,  2, 0, GL_RGBA,         GL_UNSIGNED_INT_2_10_10_10_REV,  GL_UNSIGNED_NORMALIZED, false, RequireESVersion<3>,                                    AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB10_A2UI,        RGBAFormat(10, 10, 10,  2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV,  GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    NeverSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_SRGB8,             RGBAFormat( 8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireESVersionOrExtension<3, &Extensions::sRGB>,      NeverSupported,  AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_SRGB8_ALPHA8,      RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireESVersionOrExtension<3, &Extensions::sRGB>,      AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_R11F_G11F_B10F,    RGBAFormat(11, 11, 10,  0, 0, GL_RGB,          GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT,               false, RequireESVersion<3>,                                    RequireExtension<&Extensions::colorBufferFloat>, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB9_E5,           RGBAFormat( 9,  9,  9,  0, 5, GL_RGB,          GL_UNSIGNED_INT_5_9_9_9_REV,     GL_FLOAT,               false, RequireESVersion<3>,                                    NeverSupported,  AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_R8I,               RGBAFormat( 8,  0,  0,  0, 0, GL_RED_INTEGER,  GL_BYTE,                         GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_R8UI,              RGBAFormat( 8,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_R16I,              RGBAFormat(16,  0,  0,  0, 0, GL_RED_INTEGER,  GL_SHORT,                        GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_R16UI,             RGBAFormat(16,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_R32I,              RGBAFormat(32,  0,  0,  0, 0, GL_RED_INTEGER,  GL_INT,                          GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_R32UI,             RGBAFormat(32,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RG8I,              RGBAFormat( 8,  8,  0,  0, 0, GL_RG_INTEGER,   GL_BYTE,                         GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RG8UI,             RGBAFormat( 8,  8,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RG16I,             RGBAFormat(16, 16,  0,  0, 0, GL_RG_INTEGER,   GL_SHORT,                        GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RG16UI,            RGBAFormat(16, 16,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RG32I,             RGBAFormat(32, 32,  0,  0, 0, GL_RG_INTEGER,   GL_INT,                          GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RG32UI,            RGBAFormat(32, 32,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB8I,             RGBAFormat( 8,  8,  8,  0, 0, GL_RGB_INTEGER,  GL_BYTE,                         GL_INT,                 false, RequireESVersion<3>,                                    NeverSupported,   NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB8UI,            RGBAFormat( 8,  8,  8,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    NeverSupported,   NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB16I,            RGBAFormat(16, 16, 16,  0, 0, GL_RGB_INTEGER,  GL_SHORT,                        GL_INT,                 false, RequireESVersion<3>,                                    NeverSupported,   NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB16UI,           RGBAFormat(16, 16, 16,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    NeverSupported,   NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB32I,            RGBAFormat(32, 32, 32,  0, 0, GL_RGB_INTEGER,  GL_INT,                          GL_INT,                 false, RequireESVersion<3>,                                    NeverSupported,   NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB32UI,           RGBAFormat(32, 32, 32,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    NeverSupported,   NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGBA8I,            RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA_INTEGER, GL_BYTE,                         GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGBA8UI,           RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGBA16I,           RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT,                        GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGBA16UI,          RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGBA32I,           RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT,                          GL_INT,                 false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGBA32UI,          RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireESVersion<3>,                                    AlwaysSupported,  NeverSupported)));
+    //                               | Internal format     |          | R | G | B | A |S | Format         | Type                           | Component type        | SRGB | Texture supported                        | Renderable                               | Filterable    |
+    map.insert(InternalFormatInfoPair(GL_R8,                RGBAFormat( 8,  0,  0,  0, 0, GL_RED,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::textureRG>, RequireESOrExt<3, &Extensions::textureRG>, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_R8_SNORM,          RGBAFormat( 8,  0,  0,  0, 0, GL_RED,          GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireES<3>,                              NeverSupported,                            AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RG8,               RGBAFormat( 8,  8,  0,  0, 0, GL_RG,           GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::textureRG>, RequireESOrExt<3, &Extensions::textureRG>, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RG8_SNORM,         RGBAFormat( 8,  8,  0,  0, 0, GL_RG,           GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireES<3>,                              NeverSupported,                            AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB8,              RGBAFormat( 8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::rgb8rgba8>, RequireESOrExt<3, &Extensions::rgb8rgba8>, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB8_SNORM,        RGBAFormat( 8,  8,  8,  0, 0, GL_RGB,          GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireES<3>,                              NeverSupported,                            AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB565,            RGBAFormat( 5,  6,  5,  0, 0, GL_RGB,          GL_UNSIGNED_SHORT_5_6_5,         GL_UNSIGNED_NORMALIZED, false, RequireES<2>,                              RequireES<2>,                              AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGBA4,             RGBAFormat( 4,  4,  4,  4, 0, GL_RGBA,         GL_UNSIGNED_SHORT_4_4_4_4,       GL_UNSIGNED_NORMALIZED, false, RequireES<2>,                              RequireES<2>,                              AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB5_A1,           RGBAFormat( 5,  5,  5,  1, 0, GL_RGBA,         GL_UNSIGNED_SHORT_5_5_5_1,       GL_UNSIGNED_NORMALIZED, false, RequireES<2>,                              RequireES<2>,                              AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGBA8,             RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::rgb8rgba8>, RequireESOrExt<3, &Extensions::rgb8rgba8>, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGBA8_SNORM,       RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA,         GL_BYTE,                         GL_SIGNED_NORMALIZED,   false, RequireES<3>,                              NeverSupported,                            AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB10_A2,          RGBAFormat(10, 10, 10,  2, 0, GL_RGBA,         GL_UNSIGNED_INT_2_10_10_10_REV,  GL_UNSIGNED_NORMALIZED, false, RequireES<3>,                              RequireES<3>,                              AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB10_A2UI,        RGBAFormat(10, 10, 10,  2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV,  GL_UNSIGNED_INT,        false, RequireES<3>,                              NeverSupported,                            NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_SRGB8,             RGBAFormat( 8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireESOrExt<3, &Extensions::sRGB>,      NeverSupported,                            AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_SRGB8_ALPHA8,      RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                GL_UNSIGNED_NORMALIZED, true,  RequireESOrExt<3, &Extensions::sRGB>,      RequireESOrExt<3, &Extensions::sRGB>,      AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_R11F_G11F_B10F,    RGBAFormat(11, 11, 10,  0, 0, GL_RGB,          GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT,               false, RequireES<3>,                              RequireExt<&Extensions::colorBufferFloat>, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB9_E5,           RGBAFormat( 9,  9,  9,  0, 5, GL_RGB,          GL_UNSIGNED_INT_5_9_9_9_REV,     GL_FLOAT,               false, RequireES<3>,                              NeverSupported,                            AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_R8I,               RGBAFormat( 8,  0,  0,  0, 0, GL_RED_INTEGER,  GL_BYTE,                         GL_INT,                 false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_R8UI,              RGBAFormat( 8,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_R16I,              RGBAFormat(16,  0,  0,  0, 0, GL_RED_INTEGER,  GL_SHORT,                        GL_INT,                 false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_R16UI,             RGBAFormat(16,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_R32I,              RGBAFormat(32,  0,  0,  0, 0, GL_RED_INTEGER,  GL_INT,                          GL_INT,                 false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_R32UI,             RGBAFormat(32,  0,  0,  0, 0, GL_RED_INTEGER,  GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RG8I,              RGBAFormat( 8,  8,  0,  0, 0, GL_RG_INTEGER,   GL_BYTE,                         GL_INT,                 false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RG8UI,             RGBAFormat( 8,  8,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RG16I,             RGBAFormat(16, 16,  0,  0, 0, GL_RG_INTEGER,   GL_SHORT,                        GL_INT,                 false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RG16UI,            RGBAFormat(16, 16,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RG32I,             RGBAFormat(32, 32,  0,  0, 0, GL_RG_INTEGER,   GL_INT,                          GL_INT,                 false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RG32UI,            RGBAFormat(32, 32,  0,  0, 0, GL_RG_INTEGER,   GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB8I,             RGBAFormat( 8,  8,  8,  0, 0, GL_RGB_INTEGER,  GL_BYTE,                         GL_INT,                 false, RequireES<3>,                              NeverSupported,                            NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB8UI,            RGBAFormat( 8,  8,  8,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireES<3>,                              NeverSupported,                            NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB16I,            RGBAFormat(16, 16, 16,  0, 0, GL_RGB_INTEGER,  GL_SHORT,                        GL_INT,                 false, RequireES<3>,                              NeverSupported,                            NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB16UI,           RGBAFormat(16, 16, 16,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireES<3>,                              NeverSupported,                            NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB32I,            RGBAFormat(32, 32, 32,  0, 0, GL_RGB_INTEGER,  GL_INT,                          GL_INT,                 false, RequireES<3>,                              NeverSupported,                            NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB32UI,           RGBAFormat(32, 32, 32,  0, 0, GL_RGB_INTEGER,  GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireES<3>,                              NeverSupported,                            NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGBA8I,            RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA_INTEGER, GL_BYTE,                         GL_INT,                 false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGBA8UI,           RGBAFormat( 8,  8,  8,  8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,                GL_UNSIGNED_INT,        false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGBA16I,           RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT,                        GL_INT,                 false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGBA16UI,          RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT,               GL_UNSIGNED_INT,        false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGBA32I,           RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT,                          GL_INT,                 false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGBA32UI,          RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT,                 GL_UNSIGNED_INT,        false, RequireES<3>,                              RequireES<3>,                              NeverSupported)));
 
-    map.insert(InternalFormatInfoPair(GL_BGRA8_EXT,         RGBAFormat( 8,  8,  8,  8, 0, GL_BGRA_EXT,     GL_UNSIGNED_BYTE,                  GL_UNSIGNED_NORMALIZED, false, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_BGRA4_ANGLEX,      RGBAFormat( 4,  4,  4,  4, 0, GL_BGRA_EXT,     GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX,    RGBAFormat( 5,  5,  5,  1, 0, GL_BGRA_EXT,     GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_BGRA8_EXT,         RGBAFormat( 8,  8,  8,  8, 0, GL_BGRA_EXT,     GL_UNSIGNED_BYTE,                  GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_BGRA4_ANGLEX,      RGBAFormat( 4,  4,  4,  4, 0, GL_BGRA_EXT,     GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX,    RGBAFormat( 5,  5,  5,  1, 0, GL_BGRA_EXT,     GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported)));
 
     // Floating point renderability and filtering is provided by OES_texture_float and OES_texture_half_float
-    //                               | Internal format     |          | D |S | Format             | Type                           | Comp   | SRGB |  Texture supported                                                                     | Renderable     | Filterable                                          |
-    //                               |                     |          |   |  |                    |                                | type   |      |                                                                                        |                |                                                     |
-    map.insert(InternalFormatInfoPair(GL_R16F,              RGBAFormat(16,  0,  0,  0, 0, GL_RED,          GL_HALF_FLOAT,                   GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>)));
-    map.insert(InternalFormatInfoPair(GL_RG16F,             RGBAFormat(16, 16,  0,  0, 0, GL_RG,           GL_HALF_FLOAT,                   GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>)));
-    map.insert(InternalFormatInfoPair(GL_RGB16F,            RGBAFormat(16, 16, 16,  0, 0, GL_RGB,          GL_HALF_FLOAT,                   GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureHalfFloat>,                          AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>)));
-    map.insert(InternalFormatInfoPair(GL_RGBA16F,           RGBAFormat(16, 16, 16, 16, 0, GL_RGBA,         GL_HALF_FLOAT,                   GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureHalfFloat>,                          AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>)));
-    map.insert(InternalFormatInfoPair(GL_R32F,              RGBAFormat(32,  0,  0,  0, 0, GL_RED,          GL_FLOAT,                        GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureFloat, &Extensions::textureRG>,     AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear>    )));
-    map.insert(InternalFormatInfoPair(GL_RG32F,             RGBAFormat(32, 32,  0,  0, 0, GL_RG,           GL_FLOAT,                        GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureFloat, &Extensions::textureRG>,     AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear>    )));
-    map.insert(InternalFormatInfoPair(GL_RGB32F,            RGBAFormat(32, 32, 32,  0, 0, GL_RGB,          GL_FLOAT,                        GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureFloat>,                              AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear>    )));
-    map.insert(InternalFormatInfoPair(GL_RGBA32F,           RGBAFormat(32, 32, 32, 32, 0, GL_RGBA,         GL_FLOAT,                        GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureFloat>,                              AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear>    )));
+    //                               | Internal format     |          | D |S | Format             | Type                                   | Comp   | SRGB |  Texture supported                                                             | Renderable                                                                    | Filterable                                    |
+    //                               |                     |          |   |  |                    |                                        | type   |      |                                                                                |                                                                               |                                               |
+    map.insert(InternalFormatInfoPair(GL_R16F,              RGBAFormat(16,  0,  0,  0, 0, GL_RED,          GL_HALF_FLOAT,                   GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureHalfFloatLinear>)));
+    map.insert(InternalFormatInfoPair(GL_RG16F,             RGBAFormat(16, 16,  0,  0, 0, GL_RG,           GL_HALF_FLOAT,                   GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureHalfFloatLinear>)));
+    map.insert(InternalFormatInfoPair(GL_RGB16F,            RGBAFormat(16, 16, 16,  0, 0, GL_RGB,          GL_HALF_FLOAT,                   GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureHalfFloat>,                               RequireESOrExt<3, &Extensions::textureHalfFloat>,                               RequireExt<&Extensions::textureHalfFloatLinear>)));
+    map.insert(InternalFormatInfoPair(GL_RGBA16F,           RGBAFormat(16, 16, 16, 16, 0, GL_RGBA,         GL_HALF_FLOAT,                   GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureHalfFloat>,                               RequireESOrExt<3, &Extensions::textureHalfFloat>,                               RequireExt<&Extensions::textureHalfFloatLinear>)));
+    map.insert(InternalFormatInfoPair(GL_R32F,              RGBAFormat(32,  0,  0,  0, 0, GL_RED,          GL_FLOAT,                        GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>,     RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>,     RequireExt<&Extensions::textureFloatLinear>    )));
+    map.insert(InternalFormatInfoPair(GL_RG32F,             RGBAFormat(32, 32,  0,  0, 0, GL_RG,           GL_FLOAT,                        GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>,     RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>,     RequireExt<&Extensions::textureFloatLinear>    )));
+    map.insert(InternalFormatInfoPair(GL_RGB32F,            RGBAFormat(32, 32, 32,  0, 0, GL_RGB,          GL_FLOAT,                        GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureFloat>,                                   RequireESOrExt<3, &Extensions::textureFloat>,                                   RequireExt<&Extensions::textureFloatLinear>    )));
+    map.insert(InternalFormatInfoPair(GL_RGBA32F,           RGBAFormat(32, 32, 32, 32, 0, GL_RGBA,         GL_FLOAT,                        GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureFloat>,                                   RequireESOrExt<3, &Extensions::textureFloat>,                                   RequireExt<&Extensions::textureFloatLinear>    )));
 
     // Depth stencil formats
-    //                               | Internal format         |                  | D |S | X | Format            | Type                             | Component type        | Supported     |
-    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16,     DepthStencilFormat(16, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,                 GL_UNSIGNED_NORMALIZED, RequireESVersion<2>,                                                    AlwaysSupported, RequireESVersionOrExtension<3, &Extensions::depthTextures>)));
-    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT24,     DepthStencilFormat(24, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                   GL_UNSIGNED_NORMALIZED, RequireESVersion<3>,                                                    AlwaysSupported, RequireESVersionOrExtension<3, &Extensions::depthTextures>)));
-    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32F,    DepthStencilFormat(32, 0,  0, GL_DEPTH_COMPONENT, GL_FLOAT,                          GL_FLOAT,               RequireESVersion<3>,                                                    AlwaysSupported, RequireESVersionOrExtension<3, &Extensions::depthTextures>)));
-    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                   GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::depthTextures>,                           AlwaysSupported, AlwaysSupported                                           )));
-    map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8,      DepthStencilFormat(24, 8,  0, GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8,              GL_UNSIGNED_NORMALIZED, RequireESVersionOrExtension<2, &Extensions::depthTextures>,             AlwaysSupported, AlwaysSupported                                           )));
-    map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8,     DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT,               RequireESVersion<3>,                                                    AlwaysSupported, AlwaysSupported                                           )));
-    map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8,        DepthStencilFormat( 0, 8,  0, GL_DEPTH_STENCIL,   GL_UNSIGNED_BYTE,                  GL_UNSIGNED_INT,        RequireESVersion<2>,                                                    AlwaysSupported, NeverSupported                                            )));
+    //                               | Internal format         |                  | D |S | X | Format            | Type                             | Component type        | Supported                                    | Renderable                                                                         | Filterable                                  |
+    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16,     DepthStencilFormat(16, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,                 GL_UNSIGNED_NORMALIZED, RequireES<2>,                                  RequireES<2>,                                                                        RequireESOrExt<3, &Extensions::depthTextures>)));
+    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT24,     DepthStencilFormat(24, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                   GL_UNSIGNED_NORMALIZED, RequireES<3>,                                  RequireES<3>,                                                                        RequireESOrExt<3, &Extensions::depthTextures>)));
+    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32F,    DepthStencilFormat(32, 0,  0, GL_DEPTH_COMPONENT, GL_FLOAT,                          GL_FLOAT,               RequireES<3>,                                  RequireES<3>,                                                                        RequireESOrExt<3, &Extensions::depthTextures>)));
+    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                   GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::depthTextures>,        RequireExt<&Extensions::depthTextures>,                                              AlwaysSupported                              )));
+    map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8,      DepthStencilFormat(24, 8,  0, GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8,              GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, &Extensions::depthTextures>, RequireESOrExtOrExt<3, &Extensions::depthTextures, &Extensions::packedDepthStencil>, AlwaysSupported                              )));
+    map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8,     DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT,               RequireES<3>,                                  RequireES<3>,                                                                        AlwaysSupported                              )));
+    map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8,        DepthStencilFormat( 0, 8,  0, GL_DEPTH_STENCIL,   GL_UNSIGNED_BYTE,                  GL_UNSIGNED_INT,        RequireES<2>,                                  RequireES<2>,                                                                        NeverSupported                               )));
 
     // Luminance alpha formats
     //                               | Internal format          |          | L | A | Format            | Type            | Component type        | Supported                                                                    | Renderable    | Filterable    |
-    map.insert(InternalFormatInfoPair(GL_ALPHA8_EXT,             LUMAFormat( 0,  8, GL_ALPHA,           GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::textureStorage>,                                 NeverSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_LUMINANCE8_EXT,         LUMAFormat( 8,  0, GL_LUMINANCE,       GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::textureStorage>,                                 NeverSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_ALPHA32F_EXT,           LUMAFormat( 0, 32, GL_ALPHA,           GL_FLOAT,         GL_FLOAT,               RequireExtensions<&Extensions::textureStorage, &Extensions::textureFloat>,     NeverSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_LUMINANCE32F_EXT,       LUMAFormat(32,  0, GL_LUMINANCE,       GL_FLOAT,         GL_FLOAT,               RequireExtensions<&Extensions::textureStorage, &Extensions::textureFloat>,     NeverSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_ALPHA16F_EXT,           LUMAFormat( 0, 16, GL_ALPHA,           GL_HALF_FLOAT,    GL_FLOAT,               RequireExtensions<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_LUMINANCE16F_EXT,       LUMAFormat(16,  0, GL_LUMINANCE,       GL_HALF_FLOAT,    GL_FLOAT,               RequireExtensions<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_LUMINANCE8_ALPHA8_EXT,  LUMAFormat( 8,  8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::textureStorage>,                                 NeverSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA32F_EXT, LUMAFormat(32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT,         GL_FLOAT,               RequireExtensions<&Extensions::textureStorage, &Extensions::textureFloat>,     NeverSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA16F_EXT, LUMAFormat(16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT,    GL_FLOAT,               RequireExtensions<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_ALPHA8_EXT,             LUMAFormat( 0,  8, GL_ALPHA,           GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>,                                      NeverSupported, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_LUMINANCE8_EXT,         LUMAFormat( 8,  0, GL_LUMINANCE,       GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>,                                      NeverSupported, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_ALPHA32F_EXT,           LUMAFormat( 0, 32, GL_ALPHA,           GL_FLOAT,         GL_FLOAT,               RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>,     NeverSupported, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_LUMINANCE32F_EXT,       LUMAFormat(32,  0, GL_LUMINANCE,       GL_FLOAT,         GL_FLOAT,               RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>,     NeverSupported, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_ALPHA16F_EXT,           LUMAFormat( 0, 16, GL_ALPHA,           GL_HALF_FLOAT,    GL_FLOAT,               RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_LUMINANCE16F_EXT,       LUMAFormat(16,  0, GL_LUMINANCE,       GL_HALF_FLOAT,    GL_FLOAT,               RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_LUMINANCE8_ALPHA8_EXT,  LUMAFormat( 8,  8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>,                                      NeverSupported, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA32F_EXT, LUMAFormat(32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT,         GL_FLOAT,               RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>,     NeverSupported, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA16F_EXT, LUMAFormat(16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT,    GL_FLOAT,               RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
 
     // Unsized formats
-    //                               | Internal format   |             | Format            | Supported                                                      | Renderable     | Filterable     |
-    map.insert(InternalFormatInfoPair(GL_ALPHA,           UnsizedFormat(GL_ALPHA,           RequireESVersion<2>,                                             NeverSupported,  AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_LUMINANCE,       UnsizedFormat(GL_LUMINANCE,       RequireESVersion<2>,                                             NeverSupported,  AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA, UnsizedFormat(GL_LUMINANCE_ALPHA, RequireESVersion<2>,                                             NeverSupported,  AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RED,             UnsizedFormat(GL_RED,             RequireESVersionOrExtension<3, &Extensions::textureRG>,          NeverSupported,  AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RG,              UnsizedFormat(GL_RG,              RequireESVersionOrExtension<3, &Extensions::textureRG>,          NeverSupported,  AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGB,             UnsizedFormat(GL_RGB,             RequireESVersion<2>,                                             AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RGBA,            UnsizedFormat(GL_RGBA,            RequireESVersion<2>,                                             AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_RED_INTEGER,     UnsizedFormat(GL_RED_INTEGER,     RequireESVersion<3>,                                             NeverSupported,  NeverSupported )));
-    map.insert(InternalFormatInfoPair(GL_RG_INTEGER,      UnsizedFormat(GL_RG_INTEGER,      RequireESVersion<3>,                                             NeverSupported,  NeverSupported )));
-    map.insert(InternalFormatInfoPair(GL_RGB_INTEGER,     UnsizedFormat(GL_RGB_INTEGER,     RequireESVersion<3>,                                             NeverSupported,  NeverSupported )));
-    map.insert(InternalFormatInfoPair(GL_RGBA_INTEGER,    UnsizedFormat(GL_RGBA_INTEGER,    RequireESVersion<3>,                                             NeverSupported,  NeverSupported )));
-    map.insert(InternalFormatInfoPair(GL_BGRA_EXT,        UnsizedFormat(GL_BGRA_EXT,        RequireExtension<&Extensions::textureFormatBGRA8888>,            AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT, UnsizedFormat(GL_DEPTH_COMPONENT, RequireESVersion<2>,                                             AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_DEPTH_STENCIL,   UnsizedFormat(GL_DEPTH_STENCIL,   RequireESVersionOrExtension<3, &Extensions::packedDepthStencil>, AlwaysSupported, AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_SRGB_EXT,        UnsizedFormat(GL_RGB,             RequireESVersionOrExtension<3, &Extensions::sRGB>,               NeverSupported,  AlwaysSupported)));
-    map.insert(InternalFormatInfoPair(GL_SRGB_ALPHA_EXT,  UnsizedFormat(GL_RGBA,            RequireESVersionOrExtension<3, &Extensions::sRGB>,               AlwaysSupported, AlwaysSupported)));
+    //                               | Internal format   |             | Format            | Supported                                         | Renderable                                        | Filterable    |
+    map.insert(InternalFormatInfoPair(GL_ALPHA,           UnsizedFormat(GL_ALPHA,           RequireES<2>,                                       NeverSupported,                                     AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_LUMINANCE,       UnsizedFormat(GL_LUMINANCE,       RequireES<2>,                                       NeverSupported,                                     AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA, UnsizedFormat(GL_LUMINANCE_ALPHA, RequireES<2>,                                       NeverSupported,                                     AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RED,             UnsizedFormat(GL_RED,             RequireESOrExt<3, &Extensions::textureRG>,          NeverSupported,                                     AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RG,              UnsizedFormat(GL_RG,              RequireESOrExt<3, &Extensions::textureRG>,          NeverSupported,                                     AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGB,             UnsizedFormat(GL_RGB,             RequireES<2>,                                       RequireES<2>,                                       AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RGBA,            UnsizedFormat(GL_RGBA,            RequireES<2>,                                       RequireES<2>,                                       AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_RED_INTEGER,     UnsizedFormat(GL_RED_INTEGER,     RequireES<3>,                                       NeverSupported,                                     NeverSupported )));
+    map.insert(InternalFormatInfoPair(GL_RG_INTEGER,      UnsizedFormat(GL_RG_INTEGER,      RequireES<3>,                                       NeverSupported,                                     NeverSupported )));
+    map.insert(InternalFormatInfoPair(GL_RGB_INTEGER,     UnsizedFormat(GL_RGB_INTEGER,     RequireES<3>,                                       NeverSupported,                                     NeverSupported )));
+    map.insert(InternalFormatInfoPair(GL_RGBA_INTEGER,    UnsizedFormat(GL_RGBA_INTEGER,    RequireES<3>,                                       NeverSupported,                                     NeverSupported )));
+    map.insert(InternalFormatInfoPair(GL_BGRA_EXT,        UnsizedFormat(GL_BGRA_EXT,        RequireExt<&Extensions::textureFormatBGRA8888>,     RequireExt<&Extensions::textureFormatBGRA8888>,     AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT, UnsizedFormat(GL_DEPTH_COMPONENT, RequireES<2>,                                       RequireES<2>,                                       AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_DEPTH_STENCIL,   UnsizedFormat(GL_DEPTH_STENCIL,   RequireESOrExt<3, &Extensions::packedDepthStencil>, RequireESOrExt<3, &Extensions::packedDepthStencil>, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_SRGB_EXT,        UnsizedFormat(GL_RGB,             RequireESOrExt<3, &Extensions::sRGB>,               NeverSupported,                                     AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_SRGB_ALPHA_EXT,  UnsizedFormat(GL_RGBA,            RequireESOrExt<3, &Extensions::sRGB>,               RequireESOrExt<3, &Extensions::sRGB>,               AlwaysSupported)));
 
     // Compressed formats, From ES 3.0.1 spec, table 3.16
     //                               | Internal format                             |                |W |H | BS |CC| Format                                      | Type            | SRGB | Supported          | Renderable           | Filterable         |
     map.insert(InternalFormatInfoPair(GL_COMPRESSED_R11_EAC,                        CompressedFormat(4, 4,  64, 1, GL_COMPRESSED_R11_EAC,                        GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
     map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_R11_EAC,                 CompressedFormat(4, 4,  64, 1, GL_COMPRESSED_SIGNED_R11_EAC,                 GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
     map.insert(InternalFormatInfoPair(GL_COMPRESSED_RG11_EAC,                       CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_RG11_EAC,                       GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
     map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_RG11_EAC,                CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_SIGNED_RG11_EAC,                GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
     map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_ETC2,                      CompressedFormat(4, 4,  64, 3, GL_COMPRESSED_RGB8_ETC2,                      GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
     map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ETC2,                     CompressedFormat(4, 4,  64, 3, GL_COMPRESSED_SRGB8_ETC2,                     GL_UNSIGNED_BYTE, true,  UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
     map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  CompressedFormat(4, 4,  64, 3, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
     map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4,  64, 3, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, true,  UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
     map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA8_ETC2_EAC,                 CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA8_ETC2_EAC,                 GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
     map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          GL_UNSIGNED_BYTE, true,  UnimplementedSupport, UnimplementedSupport, UnimplementedSupport)));
 
     // From GL_EXT_texture_compression_dxt1
-    //                               | Internal format                   |                |W |H | BS |CC| Format                            | Type            | SRGB | Supported                                           | Renderable           | Filterable         |
-    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT,    CompressedFormat(4, 4,  64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,    GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT1>, NeverSupported,       AlwaysSupported     )));
-    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,   CompressedFormat(4, 4,  64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,   GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT1>, NeverSupported,       AlwaysSupported     )));
+    //                               | Internal format                   |                |W |H | BS |CC| Format                            | Type            | SRGB | Supported                                      | Renderable    | Filterable    |
+    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT,    CompressedFormat(4, 4,  64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,    GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported)));
+    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,   CompressedFormat(4, 4,  64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,   GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported)));
 
     // From GL_ANGLE_texture_compression_dxt3
-    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT5>, NeverSupported,       AlwaysSupported     )));
+    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported)));
 
     // From GL_ANGLE_texture_compression_dxt5
-    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT5>, NeverSupported,       AlwaysSupported     )));
+    map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported)));
 
     return map;
 }
 
 static const InternalFormatInfoMap &GetInternalFormatMap()
 {
     static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap();
     return formatMap;
--- a/gfx/angle/src/libGLESv2/formatutils.h
+++ b/gfx/angle/src/libGLESv2/formatutils.h
@@ -98,9 +98,9 @@ const InternalFormat &GetInternalFormatI
 
 GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type);
 
 typedef std::set<GLenum> FormatSet;
 const FormatSet &GetAllSizedInternalFormats();
 
 }
 
-#endif LIBGLESV2_FORMATUTILS_H_
+#endif // LIBGLESV2_FORMATUTILS_H_
--- a/gfx/angle/src/libGLESv2/libGLESv2.cpp
+++ b/gfx/angle/src/libGLESv2/libGLESv2.cpp
@@ -105,17 +105,22 @@ void __stdcall glBeginQueryEXT(GLenum ta
     gl::Context *context = gl::getNonLostContext();
     if (context)
     {
         if (!ValidateBeginQuery(context, target, id))
         {
             return;
         }
 
-        context->beginQuery(target, id);
+        gl::Error error = context->beginQuery(target, id);
+        if (error.isError())
+        {
+            context->recordError(error);
+            return;
+        }
     }
 }
 
 void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
 {
     EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
 
     gl::Context *context = gl::getNonLostContext();
@@ -255,45 +260,34 @@ void __stdcall glBindTexture(GLenum targ
         {
             context->recordError(gl::Error(GL_INVALID_OPERATION));
             return;
         }
 
         switch (target)
         {
           case GL_TEXTURE_2D:
-            context->bindTexture2D(texture);
-            return;
-
           case GL_TEXTURE_CUBE_MAP:
-            context->bindTextureCubeMap(texture);
-            return;
+            break;
 
           case GL_TEXTURE_3D:
-            if (context->getClientVersion() < 3)
-            {
-                context->recordError(gl::Error(GL_INVALID_ENUM));
-                return;
-            }
-            context->bindTexture3D(texture);
-            return;
-
           case GL_TEXTURE_2D_ARRAY:
             if (context->getClientVersion() < 3)
             {
                 context->recordError(gl::Error(GL_INVALID_ENUM));
                 return;
             }
-            context->bindTexture2DArray(texture);
-            return;
+            break;
 
           default:
             context->recordError(gl::Error(GL_INVALID_ENUM));
             return;
         }
+
+        context->bindTexture(target, texture);
     }
 }
 
 void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
 {
     EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
           red, green, blue, alpha);
 
@@ -537,17 +531,22 @@ void __stdcall glBufferData(GLenum targe
         gl::Buffer *buffer = context->getState().getTargetBuffer(target);
 
         if (!buffer)
         {
             context->recordError(gl::Error(GL_INVALID_OPERATION));
             return;
         }
 
-        buffer->bufferData(data, size, usage);
+        gl::Error error = buffer->bufferData(data, size, usage);